Enhance data processing: add utility functions for year extraction and graph data population
This commit is contained in:
parent
76ad6d53ad
commit
43a686bb3b
@ -79,6 +79,8 @@ export function CativoXLivreChart({ title, subtitle, chartData, label, dataset1,
|
|||||||
|
|
||||||
const options: any = config(miniature)
|
const options: any = config(miniature)
|
||||||
|
|
||||||
|
const hasEstimated = chartData?.some((value) => value.dad_estimado)
|
||||||
|
|
||||||
const data: any = {
|
const data: any = {
|
||||||
labels,
|
labels,
|
||||||
datasets: chartData?.map(value => value.dad_estimado)?.includes(true) ? [
|
datasets: chartData?.map(value => value.dad_estimado)?.includes(true) ? [
|
||||||
@ -184,7 +186,7 @@ export function CativoXLivreChart({ title, subtitle, chartData, label, dataset1,
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<CativoXLivreChartView>
|
<CativoXLivreChartView>
|
||||||
<ChartTitle title={title} subtitle={subtitle}/>
|
{/* <ChartTitle title={title} subtitle={subtitle}/> */}
|
||||||
<div>
|
<div>
|
||||||
<Chart ref={chartRef} type='bar' options={options} data={data} />
|
<Chart ref={chartRef} type='bar' options={options} data={data} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -80,7 +80,7 @@ export default function CostIndicatorChart({ title, data1, data2, label, subtitl
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<CostIndicatorChartView>
|
<CostIndicatorChartView>
|
||||||
<ChartTitle title={title} subtitle={subtitle} />
|
{/* <ChartTitle title={title} subtitle={subtitle} /> */}
|
||||||
<Bar
|
<Bar
|
||||||
options={options}
|
options={options}
|
||||||
data={data}
|
data={data}
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
import { BarElement, CategoryScale, Chart as ChartJS, layouts, Legend, LinearScale, Title, Tooltip } from 'chart.js';
|
import { BarElement, CategoryScale, Chart as ChartJS, Legend, LinearScale, Title, Tooltip } from 'chart.js';
|
||||||
import ChartDataLabels from 'chartjs-plugin-datalabels';
|
import ChartDataLabels from 'chartjs-plugin-datalabels';
|
||||||
import 'chartjs-plugin-style';
|
import 'chartjs-plugin-style';
|
||||||
import { draw } from 'patternomaly';
|
import { draw } from 'patternomaly';
|
||||||
import { Chart } from 'react-chartjs-2';
|
import { Chart } from 'react-chartjs-2';
|
||||||
|
|
||||||
import ChartTitle from '../ChartTitle';
|
|
||||||
import { GrossAnualChartView } from './GrossAnualChartView';
|
import { GrossAnualChartView } from './GrossAnualChartView';
|
||||||
|
|
||||||
ChartJS.register(
|
ChartJS.register(
|
||||||
@ -40,7 +39,7 @@ export function GrossAnualChart({ title, subtitle, dataProps = [], label, datase
|
|||||||
// maintainAspectRatio: false,
|
// maintainAspectRatio: false,
|
||||||
layout: {
|
layout: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 50,
|
top: 0,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scales: {
|
scales: {
|
||||||
@ -56,7 +55,7 @@ export function GrossAnualChart({ title, subtitle, dataProps = [], label, datase
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
y: {
|
y: {
|
||||||
stacked: false,
|
stacked: true,
|
||||||
//max: Number.parseInt(dataProps.reduce((prev, current) => prev.economia_acumulada < current.economia_acumulada ? prev.economia_acumulada : current.economia_acumulada, 0)) + 350,
|
//max: Number.parseInt(dataProps.reduce((prev, current) => prev.economia_acumulada < current.economia_acumulada ? prev.economia_acumulada : current.economia_acumulada, 0)) + 350,
|
||||||
min: 0,
|
min: 0,
|
||||||
grid: {
|
grid: {
|
||||||
@ -79,26 +78,28 @@ export function GrossAnualChart({ title, subtitle, dataProps = [], label, datase
|
|||||||
},
|
},
|
||||||
plugins: {
|
plugins: {
|
||||||
datalabels: {
|
datalabels: {
|
||||||
|
display: true,
|
||||||
|
color: '#255488',
|
||||||
|
clip: false,
|
||||||
formatter: (value, ctx) => {
|
formatter: (value, ctx) => {
|
||||||
const percentage = (dataProps[ctx.dataIndex]?.econ_percentual * 100).toFixed(0) + "%";
|
const percentage = (dataProps[ctx.dataIndex]?.econ_percentual * 100).toFixed(0) + "%";
|
||||||
const result = `${spacement(parseInt(value).toLocaleString('pt-br'))}${percentage}\n${parseInt(value).toLocaleString('pt-br')}${spacement(parseInt(value).toLocaleString('pt-br'))}`
|
const result = `${spacement(parseInt(value).toLocaleString('pt-br'))}${percentage}\n${parseInt(value).toLocaleString('pt-br')}${spacement(parseInt(value).toLocaleString('pt-br'))}`
|
||||||
|
|
||||||
return value == null ? null : result
|
return value == null ? null : result
|
||||||
},
|
},
|
||||||
display: true,
|
anchor: 'end',
|
||||||
anchor: "end",
|
align: 'end',
|
||||||
align: "end",
|
offset: 5,
|
||||||
font: {
|
font: {
|
||||||
weight: 'bold',
|
weight: 'bold',
|
||||||
size: !miniature ? window.innerWidth / 80 : window.innerWidth / 125,
|
size: !miniature ? window.innerWidth / 80 : window.innerWidth / 125,
|
||||||
},
|
},
|
||||||
color: '#255488',
|
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
position: 'bottom' as const,
|
position: 'bottom' as const,
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
display: false,
|
display: true,
|
||||||
text: '',
|
text: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -126,7 +127,7 @@ export function GrossAnualChart({ title, subtitle, dataProps = [], label, datase
|
|||||||
{
|
{
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
label: dataset,
|
label: dataset,
|
||||||
stacked: true,
|
// stacked: true,
|
||||||
data: consolidatedData,
|
data: consolidatedData,
|
||||||
datalabels: {
|
datalabels: {
|
||||||
// backgroundColor: '#255488',
|
// backgroundColor: '#255488',
|
||||||
@ -134,19 +135,19 @@ export function GrossAnualChart({ title, subtitle, dataProps = [], label, datase
|
|||||||
// opacity: .8,
|
// opacity: .8,
|
||||||
display: (ctx) => ctx.dataIndex === 0, // Exibe apenas o primeiro
|
display: (ctx) => ctx.dataIndex === 0, // Exibe apenas o primeiro
|
||||||
},
|
},
|
||||||
borderRadius: 10,
|
skipNull: true,
|
||||||
|
borderRadius: 8,
|
||||||
backgroundColor: '#255488',
|
backgroundColor: '#255488',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
stacked: true,
|
|
||||||
label: 'Estimado',
|
label: 'Estimado',
|
||||||
spanGaps: true,
|
|
||||||
datalabels: {
|
datalabels: {
|
||||||
// keep the previous behaviour of offsetting the second estimated bar if needed
|
// keep the previous behaviour of offsetting the second estimated bar if needed
|
||||||
},
|
},
|
||||||
data: estimatedData,
|
data: estimatedData,
|
||||||
borderRadius: 10,
|
skipNull: true,
|
||||||
|
borderRadius: 8,
|
||||||
backgroundColor: draw('diagonal-right-left', '#C2d5fb'),
|
backgroundColor: draw('diagonal-right-left', '#C2d5fb'),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -154,8 +155,7 @@ export function GrossAnualChart({ title, subtitle, dataProps = [], label, datase
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<GrossAnualChartView>
|
<GrossAnualChartView>
|
||||||
|
<Chart options={options} data={data} type='bar' height={'156'} />
|
||||||
<Chart options={options} data={data} type='bar' height={150} />
|
|
||||||
</GrossAnualChartView>
|
</GrossAnualChartView>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,21 +3,23 @@ import styled from "styled-components"
|
|||||||
export const GrossAnualChartView = styled.div`
|
export const GrossAnualChartView = styled.div`
|
||||||
width: 90%;
|
width: 90%;
|
||||||
|
|
||||||
|
transform: translateY(-25px);
|
||||||
|
|
||||||
@media (max-width: 900px) {
|
@media (max-width: 900px) {
|
||||||
min-width: 20rem
|
min-width: 20rem
|
||||||
}
|
}
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
||||||
export const ChartTitleView = styled.div`
|
// export const ChartTitleView = styled.div`
|
||||||
display: flex;
|
// display: flex;
|
||||||
justify-content: center;
|
// justify-content: center;
|
||||||
align-items: center;
|
// align-items: center;
|
||||||
margin-top: 30px;
|
// margin-top: 30px;
|
||||||
|
|
||||||
flex-direction: column;
|
// flex-direction: column;
|
||||||
|
|
||||||
* {
|
// * {
|
||||||
margin: 0;
|
// margin: 0;
|
||||||
}
|
// }
|
||||||
`
|
// `
|
||||||
|
|||||||
@ -88,7 +88,7 @@ export default function GrossMensalChart({
|
|||||||
datalabels: {
|
datalabels: {
|
||||||
display: true,
|
display: true,
|
||||||
color: '#255488',
|
color: '#255488',
|
||||||
clip: true,
|
clip: false,
|
||||||
formatter: (value, ctx) => {
|
formatter: (value, ctx) => {
|
||||||
let sum = 0
|
let sum = 0
|
||||||
const dataArr = ctx.chart.data.datasets[0].data
|
const dataArr = ctx.chart.data.datasets[0].data
|
||||||
@ -152,7 +152,7 @@ export default function GrossMensalChart({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<GrossMensalChartView>
|
<GrossMensalChartView>
|
||||||
<ChartTitle title={title} subtitle={subtitle} />
|
{/* <ChartTitle title={title} subtitle={subtitle} /> */}
|
||||||
<ChartJs options={options} data={data} type={'bar'} height={'156'} />
|
<ChartJs options={options} data={data} type={'bar'} height={'156'} />
|
||||||
</GrossMensalChartView>
|
</GrossMensalChartView>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { GetServerSideProps } from 'next'
|
import { GetServerSideProps } from 'next'
|
||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
import { parseCookies } from 'nookies'
|
import { parseCookies } from 'nookies'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
// import Chart2 from '../../components/graph/Chart2'
|
// import Chart2 from '../../components/graph/Chart2'
|
||||||
import GrossMensalChart from '../../components/graph/grossMensalChart/GrossMensalChart'
|
import GrossMensalChart from '../../components/graph/grossMensalChart/GrossMensalChart'
|
||||||
@ -10,6 +10,7 @@ import PageTitle from '../../components/pageTitle/PageTitle'
|
|||||||
|
|
||||||
import getAPIClient from '../../services/ssrApi'
|
import getAPIClient from '../../services/ssrApi'
|
||||||
import { AccumulatedSavingsView } from '../../styles/layouts/economy/accumulatedSavings/AccumulatedSavingsView'
|
import { AccumulatedSavingsView } from '../../styles/layouts/economy/accumulatedSavings/AccumulatedSavingsView'
|
||||||
|
import { getLastConsolidatedYear, populateGraphDataForYear } from '../../utils/dataProcessing'
|
||||||
|
|
||||||
export default function AccumulatedSavings({graphData, years, userName}: any) {
|
export default function AccumulatedSavings({graphData, years, userName}: any) {
|
||||||
const months = [
|
const months = [
|
||||||
@ -27,6 +28,19 @@ export default function AccumulatedSavings({graphData, years, userName}: any) {
|
|||||||
'Dez'
|
'Dez'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const [processedData, setProcessedData] = useState(graphData)
|
||||||
|
const [lastConsolidatedYear, setLastConsolidatedYear] = useState<number | null>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Calculate the last consolidated year
|
||||||
|
const lastYear = getLastConsolidatedYear(graphData, true)
|
||||||
|
setLastConsolidatedYear(lastYear)
|
||||||
|
|
||||||
|
// Populate graph data with consolidated and estimated data for that year
|
||||||
|
const populatedData = populateGraphDataForYear(graphData, lastYear)
|
||||||
|
setProcessedData(populatedData)
|
||||||
|
}, [graphData])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AccumulatedSavingsView>
|
<AccumulatedSavingsView>
|
||||||
<Head>
|
<Head>
|
||||||
@ -37,8 +51,8 @@ export default function AccumulatedSavings({graphData, years, userName}: any) {
|
|||||||
</Header>
|
</Header>
|
||||||
<section>
|
<section>
|
||||||
<GrossMensalChart title='' subtitle=''
|
<GrossMensalChart title='' subtitle=''
|
||||||
data1={graphData}
|
data1={processedData}
|
||||||
data2={graphData}
|
data2={processedData}
|
||||||
label={months}
|
label={months}
|
||||||
/>
|
/>
|
||||||
{/* <SingleBar title='' subtitle='' dataset='Consolidada'
|
{/* <SingleBar title='' subtitle='' dataset='Consolidada'
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import PageTitle from '../../components/pageTitle/PageTitle'
|
|||||||
import getAPIClient from '../../services/ssrApi'
|
import getAPIClient from '../../services/ssrApi'
|
||||||
import { CostIndicatorView } from '../../styles/layouts/economy/costIndicator/CostIndicatorView'
|
import { CostIndicatorView } from '../../styles/layouts/economy/costIndicator/CostIndicatorView'
|
||||||
import { api } from '../../services/api';
|
import { api } from '../../services/api';
|
||||||
|
import { getLastConsolidatedYear, populateGraphDataForYear } from '../../utils/dataProcessing'
|
||||||
|
|
||||||
export default function CostIndicator({graphData, userName, clients}: any) {
|
export default function CostIndicator({graphData, userName, clients}: any) {
|
||||||
const [unity, setUnity] = useState('');
|
const [unity, setUnity] = useState('');
|
||||||
@ -35,6 +36,18 @@ export default function CostIndicator({graphData, userName, clients}: any) {
|
|||||||
]
|
]
|
||||||
|
|
||||||
const [graphDataState, setGraphDataState] = useState([]);
|
const [graphDataState, setGraphDataState] = useState([]);
|
||||||
|
const [processedGraphData, setProcessedGraphData] = useState(graphData)
|
||||||
|
const [lastConsolidatedYear, setLastConsolidatedYear] = useState<number | null>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Calculate the last consolidated year
|
||||||
|
const lastYear = getLastConsolidatedYear(graphData, true)
|
||||||
|
setLastConsolidatedYear(lastYear)
|
||||||
|
|
||||||
|
// Populate graph data with consolidated and estimated data for that year
|
||||||
|
const populatedData = populateGraphDataForYear(graphData, lastYear)
|
||||||
|
setProcessedGraphData(populatedData)
|
||||||
|
}, [graphData])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
api.post('/economy/estimates', unity!==''?{
|
api.post('/economy/estimates', unity!==''?{
|
||||||
@ -42,7 +55,14 @@ export default function CostIndicator({graphData, userName, clients}: any) {
|
|||||||
{"type" : "=", "field":"dados_cadastrais.cod_smart_unidade", "value": unity}
|
{"type" : "=", "field":"dados_cadastrais.cod_smart_unidade", "value": unity}
|
||||||
]
|
]
|
||||||
}:{}).then(res => {
|
}:{}).then(res => {
|
||||||
setGraphDataState(res.data.data)
|
// Apply data processing to filtered result
|
||||||
|
if (res.data.data && res.data.data.length > 0) {
|
||||||
|
const lastYear = getLastConsolidatedYear(res.data.data, true)
|
||||||
|
const populatedData = populateGraphDataForYear(res.data.data, lastYear)
|
||||||
|
setGraphDataState(populatedData)
|
||||||
|
} else {
|
||||||
|
setGraphDataState(res.data.data)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}, [unity])
|
}, [unity])
|
||||||
|
|
||||||
@ -75,12 +95,16 @@ export default function CostIndicator({graphData, userName, clients}: any) {
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
<section>
|
<section>
|
||||||
<CostIndicatorChart title='' subtitle=''
|
<CostIndicatorChart title='' subtitle=''
|
||||||
data1={unity!==''? graphDataState.filter((value, index) => value.mes.slice(4, 8).includes('2021'))
|
data1={unity!==''? graphDataState.filter((value, index) => value.mes.slice(0, 4).includes(lastConsolidatedYear?.toString() || ''))
|
||||||
|
.map(value => value?.custo_unit && !!parseInt(value?.custo_unit) ? value.custo_unit : null)
|
||||||
:
|
:
|
||||||
graphData.filter((value, index) => value.mes.slice(4, 8).includes('2021'))}
|
processedGraphData.filter((value, index) => value.mes.slice(0, 4).includes(lastConsolidatedYear?.toString() || ''))
|
||||||
data2={unity!==''? graphDataState.filter((value, index) => value.mes.slice(4, 8).includes('2022'))
|
.map(value => value?.custo_unit && !!parseInt(value?.custo_unit) ? value.custo_unit : null)}
|
||||||
|
data2={unity!==''? graphDataState.filter((value, index) => value.mes.slice(0, 4).includes(lastConsolidatedYear?.toString() || ''))
|
||||||
|
.map(value => value?.custo_unit && !!parseInt(value?.custo_unit) ? value.custo_unit : null)
|
||||||
:
|
:
|
||||||
graphData.filter((value, index) => value.mes.slice(4, 8).includes('2022'))}
|
processedGraphData.filter((value, index) => value.mes.slice(0, 4).includes(lastConsolidatedYear?.toString() || ''))
|
||||||
|
.map(value => value?.custo_unit && !!parseInt(value?.custo_unit) ? value.custo_unit : null)}
|
||||||
label={months}
|
label={months}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import CostIndicatorChart from '../../components/graph/costIndicatorChart'
|
|||||||
import { GrossAnualChart } from '../../components/graph/grossAnualChart/GrossAnualChart'
|
import { GrossAnualChart } from '../../components/graph/grossAnualChart/GrossAnualChart'
|
||||||
import GrossMensalChart from '../../components/graph/grossMensalChart/GrossMensalChart'
|
import GrossMensalChart from '../../components/graph/grossMensalChart/GrossMensalChart'
|
||||||
import getAPIClient from '../../services/ssrApi'
|
import getAPIClient from '../../services/ssrApi'
|
||||||
|
import { getLastConsolidatedYear, populateGraphDataForYear } from '../../utils/dataProcessing'
|
||||||
|
|
||||||
import Box from '@mui/material/Box'
|
import Box from '@mui/material/Box'
|
||||||
import Modal from '@mui/material/Modal'
|
import Modal from '@mui/material/Modal'
|
||||||
@ -66,30 +67,41 @@ export default function Dashboard({ grossAnualGraph, grossAnualYears, grossMensa
|
|||||||
|
|
||||||
const [lastDataBrutaMensalS, setLastDataBrutaMensal] = useState('')
|
const [lastDataBrutaMensalS, setLastDataBrutaMensal] = useState('')
|
||||||
const [lastDataBrutaAnualS, setLastDataBrutaAnual] = useState('')
|
const [lastDataBrutaAnualS, setLastDataBrutaAnual] = useState('')
|
||||||
|
const [processedMensalData, setProcessedMensalData] = useState(grossMensalGraph)
|
||||||
|
const [lastConsolidatedYear, setLastConsolidatedYear] = useState<number | null>(null)
|
||||||
|
|
||||||
const [open, setOpen] = useState(true);
|
const [open, setOpen] = useState(true);
|
||||||
const handleOpen = () => setOpen(true);
|
const handleOpen = () => setOpen(true);
|
||||||
const handleClose = () => setOpen(false);
|
const handleClose = () => setOpen(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// Calculate the last consolidated year
|
||||||
|
const lastYear = getLastConsolidatedYear(grossMensalGraph, true)
|
||||||
|
setLastConsolidatedYear(lastYear)
|
||||||
|
|
||||||
|
// Populate graph data with consolidated and estimated data for that year
|
||||||
|
const populatedData = populateGraphDataForYear(grossMensalGraph, lastYear)
|
||||||
|
setProcessedMensalData(populatedData)
|
||||||
|
|
||||||
|
// Calculate last data values
|
||||||
let lastDataMensal = '0'
|
let lastDataMensal = '0'
|
||||||
let lastDataAnual = '0'
|
let lastDataAnual = '0'
|
||||||
let index = 0
|
let index = 0
|
||||||
|
|
||||||
while (index < grossMensalGraph.length) {
|
while (index < populatedData.length) {
|
||||||
if (!grossMensalGraph[index].dad_estimado && grossMensalGraph[index].economia_acumulada !== null)
|
if (!populatedData[index].dad_estimado && populatedData[index].economia_acumulada !== null)
|
||||||
lastDataMensal = grossMensalGraph[index].economia_acumulada
|
lastDataMensal = String(populatedData[index].economia_acumulada)
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
setLastDataBrutaMensal(`${parseFloat(lastDataMensal).toFixed(3)}`)
|
setLastDataBrutaMensal(`${parseFloat(lastDataMensal).toFixed(3)}`)
|
||||||
index = 0
|
index = 0
|
||||||
while (index < grossAnualGraph.length) {
|
while (index < grossAnualGraph.length) {
|
||||||
if (!grossAnualGraph[index].dad_estimado)
|
if (!grossAnualGraph[index].dad_estimado)
|
||||||
lastDataAnual = grossAnualGraph[index].economia_acumulada
|
lastDataAnual = String(grossAnualGraph[index].economia_acumulada)
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
setLastDataBrutaAnual(`${parseFloat(lastDataAnual).toFixed(3)}`)
|
setLastDataBrutaAnual(`${parseFloat(lastDataAnual).toFixed(3)}`)
|
||||||
}, [])
|
}, [grossMensalGraph, grossAnualGraph])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardView>
|
<DashboardView>
|
||||||
@ -126,8 +138,8 @@ export default function Dashboard({ grossAnualGraph, grossAnualYears, grossMensa
|
|||||||
<GraphCard title='Economia Mensal' subtitle='Economia Bruta Estimada e Acumulada Mensal - Valores em R$ x mil'>
|
<GraphCard title='Economia Mensal' subtitle='Economia Bruta Estimada e Acumulada Mensal - Valores em R$ x mil'>
|
||||||
<AccumulatedEconomyTitle value={lastDataBrutaMensalS} />
|
<AccumulatedEconomyTitle value={lastDataBrutaMensalS} />
|
||||||
<GrossMensalChart title='' subtitle=''
|
<GrossMensalChart title='' subtitle=''
|
||||||
data1={grossMensalGraph}
|
data1={processedMensalData}
|
||||||
data2={grossMensalGraph}
|
data2={processedMensalData}
|
||||||
label={months}
|
label={months}
|
||||||
miniature
|
miniature
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import { api } from '../../services/api';
|
|||||||
import getAPIClient from '../../services/ssrApi';
|
import getAPIClient from '../../services/ssrApi';
|
||||||
import { TableHeader } from '../../styles/layouts/pld/PldView';
|
import { TableHeader } from '../../styles/layouts/pld/PldView';
|
||||||
import RenderIf from '../../utils/renderIf';
|
import RenderIf from '../../utils/renderIf';
|
||||||
|
import { getLastConsolidatedYear, populateGraphDataForYear } from '../../utils/dataProcessing';
|
||||||
|
|
||||||
import Tab from '@mui/material/Tab';
|
import Tab from '@mui/material/Tab';
|
||||||
import Tabs from '@mui/material/Tabs';
|
import Tabs from '@mui/material/Tabs';
|
||||||
@ -32,6 +33,8 @@ export default function economy({ userName, anual, years, brutaMensal, catLiv, c
|
|||||||
|
|
||||||
const [catLivDataState, setCatLivDataState] = useState(null);
|
const [catLivDataState, setCatLivDataState] = useState(null);
|
||||||
const [indicatorDataState, setIndicatorDataState] = useState(null);
|
const [indicatorDataState, setIndicatorDataState] = useState(null);
|
||||||
|
const [processedBrutaMensal, setProcessedBrutaMensal] = useState(brutaMensal)
|
||||||
|
const [lastConsolidatedYear, setLastConsolidatedYear] = useState<number | null>(null)
|
||||||
|
|
||||||
const currentYear = new Date().getUTCFullYear()
|
const currentYear = new Date().getUTCFullYear()
|
||||||
const previousYear = new Date().getUTCFullYear() - 1
|
const previousYear = new Date().getUTCFullYear() - 1
|
||||||
@ -52,13 +55,24 @@ export default function economy({ userName, anual, years, brutaMensal, catLiv, c
|
|||||||
]
|
]
|
||||||
|
|
||||||
const [lastDataBruta, setLastDataBruta] = useState('')
|
const [lastDataBruta, setLastDataBruta] = useState('')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Calculate the last consolidated year
|
||||||
|
const lastYear = getLastConsolidatedYear(brutaMensal, true)
|
||||||
|
setLastConsolidatedYear(lastYear)
|
||||||
|
|
||||||
|
// Populate graph data with consolidated and estimated data for that year
|
||||||
|
const populatedData = populateGraphDataForYear(brutaMensal, lastYear)
|
||||||
|
setProcessedBrutaMensal(populatedData)
|
||||||
|
}, [brutaMensal])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let lastData = '0'
|
let lastData = '0'
|
||||||
let index = 0
|
let index = 0
|
||||||
if (economyMenu) {
|
if (economyMenu) {
|
||||||
while (index < brutaMensal.length) {
|
while (index < processedBrutaMensal.length) {
|
||||||
if (!brutaMensal[index].dad_estimado)
|
if (!processedBrutaMensal[index].dad_estimado)
|
||||||
lastData = brutaMensal[index].economia_acumulada
|
lastData = processedBrutaMensal[index].economia_acumulada
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -69,7 +83,7 @@ export default function economy({ userName, anual, years, brutaMensal, catLiv, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
setLastDataBruta(`${parseFloat(lastData).toFixed(3)}`)
|
setLastDataBruta(`${parseFloat(lastData).toFixed(3)}`)
|
||||||
}, [economyMenu])
|
}, [economyMenu, processedBrutaMensal])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(indicatorDataState)
|
console.log(indicatorDataState)
|
||||||
}, [indicatorDataState])
|
}, [indicatorDataState])
|
||||||
@ -148,8 +162,8 @@ export default function economy({ userName, anual, years, brutaMensal, catLiv, c
|
|||||||
<RenderIf isTrue={economyMenu === 1}>
|
<RenderIf isTrue={economyMenu === 1}>
|
||||||
<section>
|
<section>
|
||||||
<GrossMensalChart title='' subtitle=''
|
<GrossMensalChart title='' subtitle=''
|
||||||
data1={brutaMensal}
|
data1={processedBrutaMensal}
|
||||||
data2={brutaMensal}
|
data2={processedBrutaMensal}
|
||||||
label={months}
|
label={months}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -16,11 +16,24 @@ import getAPIClient from '../../services/ssrApi'
|
|||||||
import { EstimatedCostView } from '../../styles/layouts/economy/estimatedCost/EstimatedCostView'
|
import { EstimatedCostView } from '../../styles/layouts/economy/estimatedCost/EstimatedCostView'
|
||||||
|
|
||||||
import { api } from '../../services/api'
|
import { api } from '../../services/api'
|
||||||
|
import { getLastConsolidatedYear, populateGraphDataForYear } from '../../utils/dataProcessing'
|
||||||
|
|
||||||
export default function EstimatedCost({graphData, userName, clients}: any) {
|
export default function EstimatedCost({graphData, userName, clients}: any) {
|
||||||
const [unity, setUnity] = useState<string>(null);
|
const [unity, setUnity] = useState<string>(null);
|
||||||
|
|
||||||
const [graphDataState, setGraphDataState] = useState(null);
|
const [graphDataState, setGraphDataState] = useState(null);
|
||||||
|
const [processedGraphData, setProcessedGraphData] = useState(graphData)
|
||||||
|
const [lastConsolidatedYear, setLastConsolidatedYear] = useState<number | null>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Calculate the last consolidated year
|
||||||
|
const lastYear = getLastConsolidatedYear(graphData, true)
|
||||||
|
setLastConsolidatedYear(lastYear)
|
||||||
|
|
||||||
|
// Populate graph data with consolidated and estimated data for that year
|
||||||
|
const populatedData = populateGraphDataForYear(graphData, lastYear)
|
||||||
|
setProcessedGraphData(populatedData)
|
||||||
|
}, [graphData])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
api.post('/economy/estimates', unity!==''?{
|
api.post('/economy/estimates', unity!==''?{
|
||||||
@ -28,7 +41,14 @@ export default function EstimatedCost({graphData, userName, clients}: any) {
|
|||||||
{"type" : "=", "field":"dados_cadastrais.cod_smart_unidade", "value": unity}
|
{"type" : "=", "field":"dados_cadastrais.cod_smart_unidade", "value": unity}
|
||||||
]
|
]
|
||||||
}:{}).then(res => {
|
}:{}).then(res => {
|
||||||
setGraphDataState(res.data.data)
|
// Apply data processing to filtered result
|
||||||
|
if (res.data.data && res.data.data.length > 0) {
|
||||||
|
const lastYear = getLastConsolidatedYear(res.data.data, true)
|
||||||
|
const populatedData = populateGraphDataForYear(res.data.data, lastYear)
|
||||||
|
setGraphDataState(populatedData)
|
||||||
|
} else {
|
||||||
|
setGraphDataState(res.data.data)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}, [unity])
|
}, [unity])
|
||||||
|
|
||||||
@ -60,7 +80,7 @@ export default function EstimatedCost({graphData, userName, clients}: any) {
|
|||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<section>
|
<section>
|
||||||
<CativoXLivreChart chartData={unity!==null? graphDataState : graphData}
|
<CativoXLivreChart chartData={unity!==null? graphDataState : processedGraphData}
|
||||||
dataset1="Economia (R$)" dataset2='Est. Cativo' dataset3='Est. Livre'
|
dataset1="Economia (R$)" dataset2='Est. Cativo' dataset3='Est. Livre'
|
||||||
label={['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez']} title='' subtitle='' barLabel hashurado/>
|
label={['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez']} title='' subtitle='' barLabel hashurado/>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
287
src/utils/dataProcessing.ts
Normal file
287
src/utils/dataProcessing.ts
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
/**
|
||||||
|
* Utility functions to process economy data from API
|
||||||
|
* Calculates the year with the last consolidated data and populates graphs accordingly
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface EconomyData {
|
||||||
|
ano?: string | number;
|
||||||
|
mes?: string;
|
||||||
|
economia_acumulada?: number;
|
||||||
|
economia_mensal?: number;
|
||||||
|
dad_estimado: boolean;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract year from mes field supporting multiple formats
|
||||||
|
* Supports: "YYYY-MM-DD", "MMM/YYYY", "MM/YYYY"
|
||||||
|
* @param mesValue - The mes field value
|
||||||
|
* @returns Year as number
|
||||||
|
*/
|
||||||
|
function extractYearFromMes(mesValue: string): number {
|
||||||
|
const mesStr = mesValue.toString();
|
||||||
|
|
||||||
|
// Handle "YYYY-MM-DD" format
|
||||||
|
if (mesStr.includes('-')) {
|
||||||
|
const yearStr = mesStr.split('-')[0];
|
||||||
|
return parseInt(yearStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle "MMM/YYYY" or "MM/YYYY" format
|
||||||
|
if (mesStr.includes('/')) {
|
||||||
|
const yearStr = mesStr.split('/')[1];
|
||||||
|
return parseInt(yearStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: try to parse as number if it's just a year
|
||||||
|
const parsed = parseInt(mesStr);
|
||||||
|
return !isNaN(parsed) ? parsed : new Date().getFullYear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the year with the last consolidated (non-estimated) data
|
||||||
|
* @param data - Array of economy data
|
||||||
|
* @param isMonthly - If true, extract year from 'mes' field; if false, use 'ano' field
|
||||||
|
* @returns The year with the last consolidated data
|
||||||
|
*/
|
||||||
|
export function getLastConsolidatedYear(data: EconomyData[], isMonthly: boolean = false): number {
|
||||||
|
if (!data || data.length === 0) {
|
||||||
|
return new Date().getFullYear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter only consolidated data (dad_estimado === false)
|
||||||
|
const consolidatedData = data.filter(item => !item.dad_estimado);
|
||||||
|
|
||||||
|
// Extract all years present in the dataset (consolidated + estimated)
|
||||||
|
const allYears = data
|
||||||
|
.map(item => {
|
||||||
|
if (isMonthly && item.mes) {
|
||||||
|
return extractYearFromMes(item.mes);
|
||||||
|
}
|
||||||
|
return parseInt(item.ano?.toString() || new Date().getFullYear().toString());
|
||||||
|
})
|
||||||
|
.filter(year => !Number.isNaN(year));
|
||||||
|
|
||||||
|
// Extract years from consolidated records
|
||||||
|
const consolidatedYears = consolidatedData
|
||||||
|
.map(item => {
|
||||||
|
if (isMonthly && item.mes) {
|
||||||
|
return extractYearFromMes(item.mes);
|
||||||
|
}
|
||||||
|
return parseInt(item.ano?.toString() || new Date().getFullYear().toString());
|
||||||
|
})
|
||||||
|
.filter(year => !Number.isNaN(year));
|
||||||
|
|
||||||
|
// Prefer the latest consolidated year; if none, fall back to the latest year available
|
||||||
|
if (consolidatedYears.length > 0) {
|
||||||
|
return Math.max(...consolidatedYears);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allYears.length > 0) {
|
||||||
|
return Math.max(...allYears);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Date().getFullYear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter and prepare graph data for a specific year
|
||||||
|
* Uses consolidated data for that year and estimated data for remaining months
|
||||||
|
* @param data - Array of economy data (monthly)
|
||||||
|
* @param targetYear - The year to filter by
|
||||||
|
* @returns Processed array with consolidated and estimated data
|
||||||
|
*/
|
||||||
|
export function populateGraphDataForYear(data: EconomyData[], targetYear: number | string): EconomyData[] {
|
||||||
|
if (!data || data.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const year = parseInt(targetYear.toString());
|
||||||
|
const currentMonth = new Date().getMonth() + 1; // 1-12
|
||||||
|
const currentYear = new Date().getFullYear();
|
||||||
|
|
||||||
|
// Filter data for the target year
|
||||||
|
const yearData = data.filter(item => {
|
||||||
|
if (item.mes) {
|
||||||
|
const itemYear = extractYearFromMes(item.mes);
|
||||||
|
return itemYear === year;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// If no data for the year, try to use the latest year available to avoid empty charts
|
||||||
|
if (yearData.length === 0) {
|
||||||
|
const fallbackYear = data
|
||||||
|
.map(item => (item.mes ? extractYearFromMes(item.mes) : parseInt(item.ano?.toString() || '0')))
|
||||||
|
.filter(year => !Number.isNaN(year))
|
||||||
|
.sort((a, b) => b - a)[0];
|
||||||
|
|
||||||
|
if (!fallbackYear) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return populateGraphDataForYear(data, fallbackYear);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a map of months for quick lookup
|
||||||
|
const dataMap = new Map<number, EconomyData>();
|
||||||
|
yearData.forEach(item => {
|
||||||
|
if (item.mes) {
|
||||||
|
const mesStr = item.mes.toString();
|
||||||
|
let month = 0;
|
||||||
|
|
||||||
|
// Extract month from different formats
|
||||||
|
if (mesStr.includes('-')) {
|
||||||
|
// YYYY-MM-DD format
|
||||||
|
month = parseInt(mesStr.split('-')[1]);
|
||||||
|
} else if (mesStr.includes('/')) {
|
||||||
|
// MMM/YYYY or MM/YYYY format
|
||||||
|
const parts = mesStr.split('/');
|
||||||
|
const monthPart = parts[0];
|
||||||
|
// Try to parse as number first
|
||||||
|
month = parseInt(monthPart);
|
||||||
|
// If it's NaN, it's a month name, so we need to convert it
|
||||||
|
if (isNaN(month)) {
|
||||||
|
const monthNames = ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez'];
|
||||||
|
month = monthNames.indexOf(monthPart.toLowerCase()) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (month > 0) {
|
||||||
|
dataMap.set(month, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Build complete year data (1-12 months)
|
||||||
|
const completeYearData: EconomyData[] = [];
|
||||||
|
for (let month = 1; month <= 12; month++) {
|
||||||
|
if (dataMap.has(month)) {
|
||||||
|
completeYearData.push(dataMap.get(month)!);
|
||||||
|
} else {
|
||||||
|
// Fill missing months with estimated data
|
||||||
|
// Find the last consolidated data or use the last available data as base
|
||||||
|
const lastConsolidated = Array.from(dataMap.values())
|
||||||
|
.filter(item => !item.dad_estimado)
|
||||||
|
.sort((a, b) => {
|
||||||
|
const mesA = a.mes?.toString() || '';
|
||||||
|
const mesB = b.mes?.toString() || '';
|
||||||
|
|
||||||
|
let monthA = 0, monthB = 0;
|
||||||
|
|
||||||
|
if (mesA.includes('-')) {
|
||||||
|
monthA = parseInt(mesA.split('-')[1]);
|
||||||
|
} else if (mesA.includes('/')) {
|
||||||
|
const part = mesA.split('/')[0];
|
||||||
|
monthA = parseInt(part) || getMonthNumber(part);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesB.includes('-')) {
|
||||||
|
monthB = parseInt(mesB.split('-')[1]);
|
||||||
|
} else if (mesB.includes('/')) {
|
||||||
|
const part = mesB.split('/')[0];
|
||||||
|
monthB = parseInt(part) || getMonthNumber(part);
|
||||||
|
}
|
||||||
|
|
||||||
|
return monthB - monthA;
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
if (lastConsolidated) {
|
||||||
|
const lastConsolidatedMonth = extractMonthFromMes(lastConsolidated.mes || '');
|
||||||
|
if (month > lastConsolidatedMonth) {
|
||||||
|
// Create estimated data entry for future months
|
||||||
|
completeYearData.push({
|
||||||
|
...lastConsolidated,
|
||||||
|
mes: `${month < 10 ? '0' : ''}${month}/${year}`,
|
||||||
|
dad_estimado: true
|
||||||
|
});
|
||||||
|
} else if (dataMap.size > 0) {
|
||||||
|
// Use the first available data as template for earlier months
|
||||||
|
const firstData = Array.from(dataMap.values())[0];
|
||||||
|
completeYearData.push({
|
||||||
|
...firstData,
|
||||||
|
mes: `${month < 10 ? '0' : ''}${month}/${year}`,
|
||||||
|
dad_estimado: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (dataMap.size > 0) {
|
||||||
|
// Use the first available data as template
|
||||||
|
const firstData = Array.from(dataMap.values())[0];
|
||||||
|
completeYearData.push({
|
||||||
|
...firstData,
|
||||||
|
mes: `${month < 10 ? '0' : ''}${month}/${year}`,
|
||||||
|
dad_estimado: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return completeYearData.sort((a, b) => {
|
||||||
|
const monthA = extractMonthFromMes(a.mes || '');
|
||||||
|
const monthB = extractMonthFromMes(b.mes || '');
|
||||||
|
return monthA - monthB;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract month number from mes field
|
||||||
|
* @param mesValue - The mes field value
|
||||||
|
* @returns Month number (1-12)
|
||||||
|
*/
|
||||||
|
function extractMonthFromMes(mesValue: string): number {
|
||||||
|
const mesStr = mesValue.toString();
|
||||||
|
|
||||||
|
// Handle "YYYY-MM-DD" format
|
||||||
|
if (mesStr.includes('-')) {
|
||||||
|
return parseInt(mesStr.split('-')[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle "MMM/YYYY" or "MM/YYYY" format
|
||||||
|
if (mesStr.includes('/')) {
|
||||||
|
const monthPart = mesStr.split('/')[0];
|
||||||
|
const parsed = parseInt(monthPart);
|
||||||
|
if (!isNaN(parsed)) {
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
return getMonthNumber(monthPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; // Default to January
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert month name to month number
|
||||||
|
* @param monthName - Month name (Jan, Feb, etc. or jan, fev, etc.)
|
||||||
|
* @returns Month number (1-12)
|
||||||
|
*/
|
||||||
|
function getMonthNumber(monthName: string): number {
|
||||||
|
const months = ['jan', 'fev', 'mar', 'abr', 'mai', 'jun', 'jul', 'ago', 'set', 'out', 'nov', 'dez'];
|
||||||
|
return months.indexOf(monthName.toLowerCase()) + 1 || 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get consolidated and estimated data split for a specific year
|
||||||
|
* Returns both consolidated and estimated datasets separately
|
||||||
|
* @param data - Array of economy data
|
||||||
|
* @param targetYear - The year to filter by
|
||||||
|
* @returns Object with consolidated and estimated arrays
|
||||||
|
*/
|
||||||
|
export function getConsolidatedAndEstimatedData(
|
||||||
|
data: EconomyData[],
|
||||||
|
targetYear: number | string
|
||||||
|
): { consolidated: EconomyData[]; estimated: EconomyData[] } {
|
||||||
|
const year = parseInt(targetYear.toString());
|
||||||
|
|
||||||
|
const yearData = data.filter(item => {
|
||||||
|
if (item.mes) {
|
||||||
|
const itemYear = extractYearFromMes(item.mes);
|
||||||
|
return itemYear === year;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
const consolidated = yearData.filter(item => !item.dad_estimado);
|
||||||
|
const estimated = yearData.filter(item => item.dad_estimado);
|
||||||
|
|
||||||
|
return { consolidated, estimated };
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user