-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Design graph component (CO2 Captured and Canopy Cover) #1984
base: develop
Are you sure you want to change the base?
Changes from 22 commits
1213804
9b7385e
dd0567a
48a56fb
0fba756
1d5fc82
112cbfb
0773520
0b580e9
127bf0e
4bfc2ed
b877681
905bef8
0c17009
e26e9fb
af864b8
9081299
ee59f93
fa4dd15
e88986a
5b48d1f
32dd91a
466bbf8
338075b
ae8b71a
4029516
b6227d7
c7de0b1
09f4a45
314a4e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,10 @@ | ||
{ | ||
"satelliteAnalysis": "Satellite Analysis" | ||
"satelliteAnalysis": "Satellite Analysis", | ||
"co2CapturePerHa": "CO₂ Captured <p>(per ha.)</p>", | ||
"comparedToRegionalAverage": "Compared to regional average", | ||
"co2Removed": "CO₂ removed", | ||
"biomass": "Biomass", | ||
"yoy": "YoY", | ||
"projectLaunch": "Project Launch", | ||
"canopyCover": "Canopy Cover" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
@import '../../theme/theme'; | ||
|
||
.tooltipContainer { | ||
min-width: 100px; | ||
.header { | ||
padding: 10px 10px 8px 10px; | ||
.title { | ||
color: #333; //to be replaced | ||
font-size: $fontSmall; | ||
font-weight: 500; | ||
margin-bottom: 5px; | ||
} | ||
.subtitle { | ||
font-size: $fontXXXSmallNew; | ||
font-weight: 400; | ||
} | ||
} | ||
.body { | ||
background-color: rgba(var(--primary-color-new), 0.10); | ||
padding: 4px 10px; | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
.yoyValue { | ||
color: $secondaryColorNew; | ||
font-weight: 700; | ||
font-size: $fontXXSmallNew; | ||
} | ||
.date { | ||
font-size: 6px; //to be replaced | ||
font-weight: 500; | ||
color: $dark; | ||
opacity: 0.5; | ||
} | ||
} | ||
} | ||
|
||
.container { | ||
width: 100%; | ||
max-width: 338px; | ||
display: flex; | ||
flex-direction: column; | ||
justify-content: center; | ||
align-items: center; | ||
.graphHeading { | ||
font-size: $fontXXSmall; | ||
color: #2F3336; //to be replaced | ||
display: flex; | ||
align-items: center; | ||
padding:0 15px; | ||
gap: 2px; | ||
font-weight: 700; | ||
p { | ||
font-weight: 400; | ||
} | ||
|
||
} | ||
.graphSubheading { | ||
color: #BDBDBD; //to be replaced | ||
font-size: $fontXXXSmallNew; | ||
text-transform: lowercase; | ||
padding:0 15px; | ||
} | ||
} | ||
|
||
.titleContainer { | ||
width: 100%; | ||
max-width: 300px; | ||
} | ||
.newInfoIcon { | ||
margin-left: auto; | ||
margin-right: 6px; | ||
display: flex; | ||
align-items: center; | ||
cursor: pointer; | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,236 @@ | ||||||||||||||||||||||||||||
import React, { useEffect, useState } from 'react'; | ||||||||||||||||||||||||||||
import ReactApexChart from 'react-apexcharts'; | ||||||||||||||||||||||||||||
import styles from './Graph.module.scss'; | ||||||||||||||||||||||||||||
import ReactDOMServer from 'react-dom/server'; | ||||||||||||||||||||||||||||
import NewInfoIcon from '../icons/NewInfoIcon'; | ||||||||||||||||||||||||||||
import { ApexOptions } from 'apexcharts'; | ||||||||||||||||||||||||||||
import { Trans, useTranslation } from 'next-i18next'; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
interface TooltipProps { | ||||||||||||||||||||||||||||
headerTitle: string; | ||||||||||||||||||||||||||||
subTitle: string; | ||||||||||||||||||||||||||||
yoyValue: string; | ||||||||||||||||||||||||||||
date: string; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
export const Tooltip = ({ | ||||||||||||||||||||||||||||
headerTitle, | ||||||||||||||||||||||||||||
subTitle, | ||||||||||||||||||||||||||||
yoyValue, | ||||||||||||||||||||||||||||
date, | ||||||||||||||||||||||||||||
}: TooltipProps) => { | ||||||||||||||||||||||||||||
const { t } = useTranslation('projectDetails'); | ||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||
<div className={styles.tooltipContainer}> | ||||||||||||||||||||||||||||
<div className={styles.header}> | ||||||||||||||||||||||||||||
<p className={styles.title}>{headerTitle}</p> | ||||||||||||||||||||||||||||
<p className={styles.subtitle}>{subTitle}</p> | ||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||
<div className={styles.body}> | ||||||||||||||||||||||||||||
<p className={styles.yoyValue}> | ||||||||||||||||||||||||||||
{yoyValue} {t('yoy')} | ||||||||||||||||||||||||||||
</p> | ||||||||||||||||||||||||||||
<p className={styles.date}>{date}</p> | ||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
interface GraphProps { | ||||||||||||||||||||||||||||
title: string; | ||||||||||||||||||||||||||||
subtitle: string; | ||||||||||||||||||||||||||||
years: number[]; | ||||||||||||||||||||||||||||
series1Values: number[]; | ||||||||||||||||||||||||||||
series2Values: number[]; | ||||||||||||||||||||||||||||
tooltip: { | ||||||||||||||||||||||||||||
heading: string; | ||||||||||||||||||||||||||||
unit: string; | ||||||||||||||||||||||||||||
subheading: string; | ||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
interface CustomTooltipProps { | ||||||||||||||||||||||||||||
dataPointIndex: number; | ||||||||||||||||||||||||||||
w: { config: ApexOptions; globals: any }; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
const Graph = ({ | ||||||||||||||||||||||||||||
title, | ||||||||||||||||||||||||||||
subtitle, | ||||||||||||||||||||||||||||
years, | ||||||||||||||||||||||||||||
series1Values, | ||||||||||||||||||||||||||||
series2Values, | ||||||||||||||||||||||||||||
tooltip, | ||||||||||||||||||||||||||||
}: GraphProps) => { | ||||||||||||||||||||||||||||
const { t } = useTranslation('projectDetails'); | ||||||||||||||||||||||||||||
const [xaxisOptions, setXaxisOptions] = useState< | ||||||||||||||||||||||||||||
(number | (string | number)[])[] | ||||||||||||||||||||||||||||
>([]); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
useEffect(() => { | ||||||||||||||||||||||||||||
const newOptions = years.map((year, index) => { | ||||||||||||||||||||||||||||
if (index === 1) { | ||||||||||||||||||||||||||||
return [2020, ` ${t('projectLaunch')}`]; | ||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||
return year; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
setXaxisOptions(newOptions); | ||||||||||||||||||||||||||||
}, []); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
const options = { | ||||||||||||||||||||||||||||
fill: { | ||||||||||||||||||||||||||||
type: 'gradient', | ||||||||||||||||||||||||||||
gradient: { | ||||||||||||||||||||||||||||
shadeIntensity: 1, | ||||||||||||||||||||||||||||
opacityFrom: 0.58, | ||||||||||||||||||||||||||||
opacityTo: 0, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
chart: { | ||||||||||||||||||||||||||||
type: 'area', | ||||||||||||||||||||||||||||
width: 300, | ||||||||||||||||||||||||||||
toolbar: { | ||||||||||||||||||||||||||||
show: false, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
Comment on lines
+90
to
+96
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove hardcoded chart width for responsiveness The chart's width is hardcoded to Remove the hardcoded width: chart: {
type: 'area',
- width: 300,
toolbar: {
show: false,
},
}, 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||
tooltip: { | ||||||||||||||||||||||||||||
custom: function ({ dataPointIndex, w }: CustomTooltipProps) { | ||||||||||||||||||||||||||||
const getToolTip = () => { | ||||||||||||||||||||||||||||
const dataPoint = xaxisOptions[dataPointIndex]; | ||||||||||||||||||||||||||||
const year = Array.isArray(dataPoint) ? dataPoint[0] : dataPoint; | ||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||
<Tooltip | ||||||||||||||||||||||||||||
headerTitle={`${w.globals.series[0][dataPointIndex]}${ | ||||||||||||||||||||||||||||
tooltip.unit | ||||||||||||||||||||||||||||
} ${t(`${tooltip.heading}`)}`} | ||||||||||||||||||||||||||||
subTitle={ | ||||||||||||||||||||||||||||
tooltip.subheading | ||||||||||||||||||||||||||||
? `${w.globals.series[1][dataPointIndex]}${tooltip.unit} ${t( | ||||||||||||||||||||||||||||
`${tooltip.subheading}` | ||||||||||||||||||||||||||||
)}` | ||||||||||||||||||||||||||||
: '' | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
yoyValue={'+4%'} | ||||||||||||||||||||||||||||
date={year.toString()} | ||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
return ReactDOMServer.renderToString(getToolTip()); | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
followCursor: true, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
markers: { | ||||||||||||||||||||||||||||
size: 0, | ||||||||||||||||||||||||||||
colors: ['#fff', 'transparent'], | ||||||||||||||||||||||||||||
strokeColors: ['#219653', 'transparent'], | ||||||||||||||||||||||||||||
strokeOpacity: [1, 1], | ||||||||||||||||||||||||||||
strokeWidth: 2.2, | ||||||||||||||||||||||||||||
hover: { | ||||||||||||||||||||||||||||
size: 6, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
dataLabels: { | ||||||||||||||||||||||||||||
enabled: false, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
stroke: { | ||||||||||||||||||||||||||||
curve: 'smooth', | ||||||||||||||||||||||||||||
width: 2.2, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
xaxis: { | ||||||||||||||||||||||||||||
type: 'year', | ||||||||||||||||||||||||||||
labels: { | ||||||||||||||||||||||||||||
formatter: function (index: number) { | ||||||||||||||||||||||||||||
if (index === 2) { | ||||||||||||||||||||||||||||
return xaxisOptions[1]; | ||||||||||||||||||||||||||||
} else if (index == xaxisOptions.length) { | ||||||||||||||||||||||||||||
return xaxisOptions[index - 1]; | ||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||
return ''; | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
Comment on lines
+151
to
+159
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct x-axis label formatter function The x-axis label formatter function uses Modify the formatter function to use labels: {
- formatter: function (index: number) {
- if (index === 2) {
- return xaxisOptions[1];
- } else if (index == xaxisOptions.length) {
- return xaxisOptions[index - 1];
+ formatter: function (value: number, timestamp?: number, opts?: any) {
+ const dataPointIndex = opts?.dataPoints?.findIndex(
+ (point: any) => point.x === value
+ );
+ if (dataPointIndex === 1) {
+ return xaxisOptions[1][1];
+ } else if (dataPointIndex === xaxisOptions.length - 1) {
+ return xaxisOptions[dataPointIndex];
} else {
return '';
}
}, This ensures labels are displayed correctly based on the x-axis values.
|
||||||||||||||||||||||||||||
minHeight: 35, | ||||||||||||||||||||||||||||
style: { | ||||||||||||||||||||||||||||
colors: '#4F4F4F', | ||||||||||||||||||||||||||||
fontSize: 10, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
show: false, | ||||||||||||||||||||||||||||
axisTicks: { | ||||||||||||||||||||||||||||
show: false, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
tooltip: { | ||||||||||||||||||||||||||||
enabled: false, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
axisBorder: { | ||||||||||||||||||||||||||||
show: false, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
yaxis: { | ||||||||||||||||||||||||||||
show: false, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
grid: { | ||||||||||||||||||||||||||||
show: false, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
legend: { | ||||||||||||||||||||||||||||
show: false, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
annotations: { | ||||||||||||||||||||||||||||
xaxis: [ | ||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||
x: xaxisOptions[1], | ||||||||||||||||||||||||||||
strokeDashArray: 0, | ||||||||||||||||||||||||||||
borderColor: '#219653', | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||
const series = [ | ||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||
name: 'series1', | ||||||||||||||||||||||||||||
data: series1Values, | ||||||||||||||||||||||||||||
color: '#219653', | ||||||||||||||||||||||||||||
zIndex: 2, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||
name: 'series2', | ||||||||||||||||||||||||||||
data: series2Values, | ||||||||||||||||||||||||||||
color: '#BDBDBD', | ||||||||||||||||||||||||||||
zIndex: 1, | ||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||
]; | ||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||
<div className={styles.container}> | ||||||||||||||||||||||||||||
<div className={styles.titleContainer}> | ||||||||||||||||||||||||||||
<h5 className={styles.graphHeading}> | ||||||||||||||||||||||||||||
{title === 'co2CapturePerHa' ? ( | ||||||||||||||||||||||||||||
<Trans i18nKey="co2CapturePerHa"> | ||||||||||||||||||||||||||||
CO₂ Captured<p>(per ha.)</p> | ||||||||||||||||||||||||||||
</Trans> | ||||||||||||||||||||||||||||
) : ( | ||||||||||||||||||||||||||||
t(`${title}`) | ||||||||||||||||||||||||||||
)} | ||||||||||||||||||||||||||||
<div className={styles.newInfoIcon}> | ||||||||||||||||||||||||||||
<NewInfoIcon height={17} width={17} color={'#BDBDBD'} /> | ||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||
</h5> | ||||||||||||||||||||||||||||
<p className={styles.graphSubheading}> {t(`${subtitle}`)}</p> | ||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||
<div id="chart"> | ||||||||||||||||||||||||||||
<ReactApexChart | ||||||||||||||||||||||||||||
options={options} | ||||||||||||||||||||||||||||
series={series} | ||||||||||||||||||||||||||||
type="area" | ||||||||||||||||||||||||||||
height={153} | ||||||||||||||||||||||||||||
width={'100%'} | ||||||||||||||||||||||||||||
style={{ display: 'flex', justifyContent: 'center' }} | ||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||
<div id="html-dist"></div> | ||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
export default Graph; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import type { Meta, StoryObj } from '@storybook/react'; | ||
import Graph from '../CarbonCapture/Graph'; | ||
|
||
const meta: Meta<typeof Graph> = { | ||
component: Graph, | ||
}; | ||
|
||
export default meta; | ||
type Story = StoryObj<typeof Graph>; | ||
|
||
const years = [2019, 2020, 2021, 2022, 2023]; | ||
|
||
export const Preview: Story = { | ||
args: { | ||
years: years, | ||
title: 'co2CapturePerHa', | ||
subtitle: 'comparedToRegionalAverage', | ||
series1Values: [21.4, 21.27, 20.78, 21.7, 21.78], | ||
series2Values: [22.54, 22.65, 21.8, 21.85, 22.03], | ||
tooltip: { | ||
heading: 'co2Removed', | ||
unit: 't', | ||
subheading: 'biomass', | ||
}, | ||
}, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid hardcoding values and update dependency array
In the
useEffect
hook, the use of a hardcoded year (2020
) when setting x-axis options can lead to incorrect labeling if the actual years differ. Additionally, the dependency array is empty, which may cause issues ifyears
ort
(translations) change.Apply this diff to use dynamic year values and update the dependency array:
📝 Committable suggestion