Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 12 additions & 17 deletions src/components/chart/CardChartByGroup1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,9 @@ import { ItemCount } from '../../types';
import SelectSortBy from '../groupby/SelectSortBy';
import { useSelector } from 'react-redux';
import { RootState } from '../../stores/store';
import ChartDataFilterSlider from '../organisms/ChartDataFilterSlider';
import { EchartId } from '../types';

const foramtDataPrecision = (data: ItemCount[]) => {
const data2 = data.map((x) => {
if (typeof x.count === 'number' && !Number.isInteger(x.count)) {
return { _id: x._id, count: x.count.toFixed(1) };
}
return { _id: x._id, count: x.count };
});
return data2;
};

const CardChartByGroup1: React.FC<{}> = observer(() => {
const styles = {
divConfig: {
Expand All @@ -39,9 +31,9 @@ const CardChartByGroup1: React.FC<{}> = observer(() => {
// const { t } = useTranslation();
const [showModel, setShowModal] = useState(false);
const { filterStore } = useStore();
const { dataFilterd } = filterStore;
const reactData = toJS(dataFilterd);
const dataFormated = foramtDataPrecision(reactData);
const { dataFilterd, getChartData } = filterStore;
const chartId = EchartId.Group_1;
const dataFormated = getChartData(chartId);
const { chartType, direction } = useSelector((state: RootState) => state.appUi);

const chart = <ChartBar
Expand All @@ -54,12 +46,15 @@ const CardChartByGroup1: React.FC<{}> = observer(() => {
const memoSettingsIcon = useMemos([],
<SvgIconSettings color={'var(--onprimary-color)'} />
);
// const memoSettingsIcon = <SvgIconSettings color={'var(--onprimary-color)'} />;
// const memoSettingsIcon = <SvgIconSettings color={'var(--onprimary-color)'} />;
return (
<>
<SmallCard style={{marginBottom: '0.5rem'}}>
<div style={styles.divConfig}>
<SelectGroupBy id="Graphs.Main.SelectGroupby" />
<SelectGroupBy id="Graphs.Main.SelectGroupby" />
<div style={{ width: '40%', margin: '0 auto' }}>
<ChartDataFilterSlider id={chartId} data={dataFilterd} />
</div>
<SelectSortBy id="Graphs.Main.SelectSort"/>
</div>
<ConfigModal title="Chart Options" showModal={showModel} setShow={setShowModal}>
Expand All @@ -72,9 +67,9 @@ const CardChartByGroup1: React.FC<{}> = observer(() => {
</div>
</div>
</SmallCard>

</>
);
});

export default CardChartByGroup1;
14 changes: 10 additions & 4 deletions src/components/chart/CardChartGrpBy2.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { FC } from 'react';
import { observer } from 'mobx-react';
import { toJS } from 'mobx';
import { useStore } from '../../stores/storeConfig';
import GroupBy2 from '../../stores/filter/GroupBy2';
import SelectGroupBy from '../groupby/SelectGroupBy';
Expand All @@ -9,6 +8,8 @@ import { SmallCard } from '../common';
import ChartBar from './ChartBar';
import { RootState } from '../../stores/store';
import { useSelector } from 'react-redux';
import ChartDataFilterSlider from '../organisms/ChartDataFilterSlider';
import { EchartId } from '../types';

interface IProps { }
const CardChartGrpBy2: FC<IProps> = observer(() => {
Expand All @@ -29,11 +30,12 @@ const CardChartGrpBy2: FC<IProps> = observer(() => {
flexWrap: 'wrap',
} as React.CSSProperties;
const { filterStore } = useStore();
const { group2Dict } = filterStore;
const { group2Dict, getChartData, dataGroupby2 } = filterStore;
const chartId = EchartId.Group_2;
const dataFormated = getChartData(chartId);
const { groupBy } = group2Dict;
const { chartType, direction } = useSelector((state: RootState) => state.appUi);
const metaDAta = (groupBy as GroupBy2).getBars();
const reactDataGrp2 = toJS(filterStore.dataGroupby2);
const show = true;
return (
<div>
Expand All @@ -43,13 +45,17 @@ const CardChartGrpBy2: FC<IProps> = observer(() => {
<div style={divConstolsRow}>
<SelectGroupBy id="Graphs.Grp2" labelText="" />
{' '}
&nbsp;
&nbsp;
<SelectGroupBy2 id="Graphs" />
{/* <RangeSlider id="Graphs" label="resize" value={80} onChange={onSizeSliderChange}/> */}
<div style={{ width: '40%', margin: '0 auto' }}>
<ChartDataFilterSlider id={chartId} data={dataGroupby2} />
</div>
</div>
<hr />
<div style={styles.divChart}>
<ChartBar data={reactDataGrp2} metaData={metaDAta} chartType={chartType} dir={direction} />
<ChartBar data={dataFormated} metaData={metaDAta} chartType={chartType} dir={direction} />
</div>
</SmallCard>
)}
Expand Down
23 changes: 14 additions & 9 deletions src/components/chart/CardChartYears.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,32 @@ import { useStore } from '../../stores/storeConfig';
import { SmallCard } from '../common';
import ChartBar from './ChartBar';
import { RootState } from '../../stores/store';
import ChartDataFilterSlider from '../organisms/ChartDataFilterSlider';
import { EchartId } from '../types';

const CardChartYears: React.FC<{}> = observer(() => {
const { t } = useTranslation();
const { filterStore } = useStore();
const { dataFilterdByYears, casualtiesNames } = filterStore;
const { dataFilterdByYears, casualtiesNames, getChartData } = filterStore;
const chartId = EchartId.Years;
const dataFormated = getChartData(chartId);
const direction = useSelector((state: RootState) => state.appUi.direction);
const reactData2 = toJS(dataFilterdByYears);
const styles = {
divChart: {
width: '100%',
height: '58.5vh',
},
};
return (
<SmallCard styleType={2} header={`${t(casualtiesNames)} ${t('by-years')}`}>
<div style={styles.divChart}>
<ChartBar data={reactData2} fill="#FE9772" dir={direction} />
</div>
</SmallCard>
<SmallCard styleType={2} header={`${t(casualtiesNames)} ${t('by-years')}`}>
<div style={{ padding: '0 10px', width: '80%', margin: '0 auto' }}>
<ChartDataFilterSlider id={chartId} data={dataFilterdByYears} />
</div>
<div style={styles.divChart}>
<ChartBar data={dataFormated} fill="#FE9772" dir={direction} />
</div>
</SmallCard>
);
});

export default CardChartYears;

export default CardChartYears;
119 changes: 80 additions & 39 deletions src/components/chart/ChartBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -217,62 +217,103 @@ export const options = {

const ChartBar: React.FC<IProps> = ({ data, metaData, chartType = 'BarChart', height = 60, dir, fill = '#8884d8', }: IProps) => {
const { t } = useTranslation();
// if metaData == undefined - chart of 1 group
//if (metaData == undefined) {
const label = t('casualties');
const backgroundColor = getColorPallete(chartType, data.length, fill);
//}
// Extract labels and data
const labels = data.map(item => item._id);

// Create the chart data structure
let datasets: any;
// Separate visible items from the aggregated outside item
const outsideItem = data.find(item => item._id === 'outside_range');
const visibleItems = data.filter(item => item._id !== 'outside_range');

// Construct shared labels
const labels = visibleItems.map(item => item._id);
if (outsideItem) {
labels.push(t('outside_range'));
}

const labelPrefix = t('casualties');
const isBar = chartType === 'BarChart' || chartType === 'HorizontalBar';
const backgroundColor = getColorPallete(chartType, visibleItems.length, fill);

let chartDatasets: any[] = [];

if (metaData === undefined) {
// chart of gorup 1
const counts = data.map(item => item.count);
datasets = [
{
label: label,
data: counts,
backgroundColor: backgroundColor
},
];
// Single Dataset Chart (Category only)
const backgroundColor = getColorPallete(chartType, visibleItems.length, fill);

// Main Dataset
chartDatasets.push({
label: labelPrefix,
data: [...visibleItems.map(item => item.count), outsideItem ? null : undefined].filter(x => x !== undefined),
backgroundColor: backgroundColor,
});

// Outside Dataset (Only for Bar charts)
if (outsideItem && isBar) {
chartDatasets.push({
label: t('outside_range'),
data: [...Array(visibleItems.length).fill(null), outsideItem.count],
backgroundColor: '#FF4136',
// borderRadius: 4,
});
}
} else {
// Dynamically generate datasets based on MethData and data
datasets = metaData.map((method) => {
return {
label: t(method.key), //method.key.charAt(0).toUpperCase() + method.key.slice(1),
data: data.map(item => item[method.key] || 0), // Use key from MethData to access values in data
backgroundColor: method.color, // backgroundColor from MethData
// Grouped/Multi-Dataset Chart (e.g. Gender, Age)
// 1. Visible datasets
metaData.forEach((method) => {
chartDatasets.push({
label: t(method.key),
data: [...visibleItems.map(item => item[method.key] || 0), outsideItem ? null : undefined].filter(x => x !== undefined),
backgroundColor: method.color,
axis: 'x',
};
});
});

// 2. Summary Outside Dataset (Single combined bar for all groups)
if (outsideItem && isBar) {
// Calculate total for the specific outside candle
const totalOutside = metaData.reduce((sum, method) => sum + (outsideItem[method.key] || 0), 0);
chartDatasets.push({
label: `${t('outside_range')}`,
data: [...Array(visibleItems.length).fill(null), totalOutside],
backgroundColor: '#FF4136',
// borderRadius: 4,
// barPercentage: 0.5, // Make it look more like a "candle"
});
}
}

const chartData = {
labels: labels, // Years as labels
datasets: datasets
labels: labels,
datasets: chartDatasets
};
if (chartType === 'BarChart') {
Object.assign(options.plugins, { datalabels: datalabelsOptions });

if (chartType === 'BarChart') {
Object.assign(options.plugins, { datalabels: datalabelsOptions });
return (
<div style={{ height: '100%'}}>
<Bar options={options} data={chartData} />
</div>
);
} else if (chartType === 'PieChart') {
} else if (chartType === 'PieChart') {
// For Pie charts, we keep one dataset with all slices (including outside)
// because multiple datasets in Pie/Pie results in multi-level doughnuts.
const pieData = {
labels: labels,
datasets: [{
data: data.map(item => item.count || metaData?.reduce((s: number, m: any) => s + (item[m.key] || 0), 0)),
backgroundColor: data.map((item, index) => {
if (item._id === 'outside_range') return '#FF4136';
if (metaData) return 'grey'; // Fixed color for grouped data in pie
return Array.isArray(backgroundColor) ? backgroundColor[index % backgroundColor.length] : backgroundColor;
})
}]
};
return (
<>
<Pie options={options} data={chartData} />
<Pie options={options} data={pieData} />
</>
);
} else {
//HorizontalBar
//options.indexAxis= "y" as "y";
const options1 = ({indexAxis: "y" as "y"})
// chartData.datasets = chartData.datasets.map((dataset: any) => ({
// ...dataset,
// axis: "y",
// }));
} else {
// HorizontalBar
const options1 = ({indexAxis: "y" as "y"});
return (
<div >
<Bar options={options1} data={chartData} />
Expand Down
2 changes: 1 addition & 1 deletion src/components/map/AccidentPopUp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const AccidentsPopUp: React.FC<IProps> = (({ data: x, language }) => {
if (x.injured_type_hebrew !== undefined) {
return (
<Popup>
<div style={{fontSize: '16px'}} className={`text${language}`}>
<div style={{fontSize: '14px'}} className={`text${language}`}>
<div><span style={pStyle}>{t('When')}: </span>{x.accident_timestamp.slice(0, 16)}, {x.day_in_week_hebrew}, {x.day_night_hebrew}</div>
<div><span style={pStyle}>{t('Who')}: </span>{x.injured_type_hebrew}, {x.injury_severity_hebrew}, {x.vehicle_vehicle_type_hebrew ? `${x.vehicle_vehicle_type_hebrew}, ` : ''} {x.sex_hebrew}, {x.age_group_hebrew}, {x.population_type_hebrew}</div>
<div><span style={pStyle}>{t('Where')}: </span>
Expand Down
Loading