Situation: I get multiple datasets from my server, each dataset is loaded into a state and then split into data with keys and values([{x:'2021-10-25', y:20},...]).
My goal is to display the correct chronology for the dataLabels ('x' values) which match with the 'y' values for each dataset.
Problems:
now my code work perfectly for one dataset, but when I select two or more I get wrong chronology of dateLabels as in a link here: https://prnt.sc/26phbi5
I have tried to solve this problem through options and chartjs-adapter-date-fns or luxon but I get error: 'Error: This method is not implemented: Check that a complete date adapter is provided.'
I'll get old solving this problem soon, please, can anyone help me with this?
here is my code:
import React, { useState, useEffect } from 'react'
import { CCard, CCardBody, CCol, CButton, CButtonGroup, CRow, CFormFeedback } from '@coreui/react'
import { CChartLine } from '@coreui/react-chartjs'
import { Line } from 'react-chartjs-2'
import axios from 'axios'
import { format } from 'date-fns'
import DatePicker from 'react-datepicker'
import 'react-datepicker/dist/react-datepicker.css'
import AsyncSelect from 'react-select/async'
import Chart from 'chart.js/auto'
import 'chartjs-adapter-date-fns'
import { enUS } from 'date-fns/locale'
let token = localStorage.getItem('token')
const headers = {
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
Accept: '*/*',
},
}
const SalesByClubsCharts = () => {
const [period, setPeriod] = useState('day')
const [startDate, setStartDate] = useState(null)
const [endDate, setEndDate] = useState(null)
const [selectedGroup, setSelectedGroup] = useState('')
const [selectedGroupId, setSelectedGroupId] = useState(null)
const [chartData, setChartData] = useState({})
// handle selection
const handleChange = (value) => {
let groupsId = value.map((i) => i.id).join(', ')
setSelectedGroupId(groupsId)
setSelectedGroup(value)
}
// fetch the options for showing in select field
const loadOptions = async (inputText) => {
const response = await fetch(
`${process.env.REACT_APP_BASE_URL}admin/group/simple?search=${inputText}`,
{
method: 'GET',
mode: 'cors',
headers: headers.headers,
},
)
const json = await response.json()
return json
}
// creating colors for datasets
const dynamicColors = function () {
let r = Math.floor(Math.random() * 255)
let g = Math.floor(Math.random() * 255)
let b = Math.floor(Math.random() * 255)
return 'rgb(' + r + ',' + g + ',' + b + ')'
}
useEffect(() => {
let isCancelled = false
const fetchChartData = async () => {
let selectStart = startDate === null ? '' : `&selectStart=${startDate.toISOString()}`
let selectEnd = endDate === null ? '' : `&selectEnd=${endDate.toISOString()}`
let selectedIds = selectedGroupId === null ? '' : `groups=${selectedGroupId}&`
let datasets = []
await axios
.get(
`${process.env.REACT_APP_BASE_URL}admin/charts/sales?${selectedIds}period=${period}${selectStart}${selectEnd}`,
headers,
)
.then((response) => {
if (!isCancelled) {
let groupsValues = Object.values(response.data.groups)
let groupsData = Object.entries(response.data.groups)
console.log('groupsValues', groupsValues)
console.log('groupsData:', groupsData)
// check if any groupID is selected otherwise it displays all groups
if (/\d/.test(selectedIds)) {
groupsData.forEach((group) => {
let x_y_data = group[1].map((i) => ({
y: i.sales.toString().slice(0, -2),
x: format(new Date(i.date), 'yyyy-MM-dd'),
}))
console.log('x_y_data:', x_y_data)
let color = dynamicColors()
const newDataset = {
label: group[0].toString(),
backgroundColor: color,
borderColor: color,
data: x_y_data,
}
datasets.push(newDataset)
console.log('datasets:', datasets)
})
setChartData({
datasets,
})
}
}
})
.catch((error) => console.log(error))
}
fetchChartData()
return () => (isCancelled = true)
}, [period, startDate, endDate, selectedGroupId])
return (
<CCard className="mb-4">
<CCardBody>
<CRow>
<CCol sm={2}>
<h5 id="traffic" className="card-title mb-0">
Sales by Clubs
</h5>
<div className="small text-medium-emphasis"></div>
</CCol>
<CCol sm={4}>
<AsyncSelect
isMulti
cacheOptions
defaultOptions
placeholder={'Select groups to compare'}
value={selectedGroup}
getOptionLabel={(e) => e.name + ' id: ' + e.id}
getOptionValue={(e) => e.id}
loadOptions={loadOptions}
onChange={handleChange}
/>
</CCol>
<CCol sm={3}>
<DatePicker
placeholderText="Select a period"
dateFormat="yyyy-MM-dd"
minDate={new Date('2021-10-01')}
selected={startDate}
onChange={(dates) => {
const [start, end] = dates
setStartDate(start)
setEndDate(end)
}}
startDate={startDate}
endDate={endDate}
selectsRange
/>
<CFormFeedback invalid>Please provide a valid date.</CFormFeedback>
</CCol>
<CCol sm={3} className="d-none d-md-block">
<CButtonGroup className="float-end me-3">
{['day', 'week', 'month'].map((value) => (
<CButton
color="outline-secondary"
key={value}
className="mx-0"
onClick={() => {
setPeriod(value)
}}
>
{value}
</CButton>
))}
</CButtonGroup>
</CCol>
</CRow>
<div>
<Line data={chartData} />
</div>
</CCardBody>
</CCard>
)
}
export default SalesByClubsCharts
and here is a chunk of my data example for two datasets:
[
{y: '2', x: '2021-10-14'}, {y: '50', x: '2021-10-16'}, {y: '115', x: '2021-10-18'},
{y: '105', x: '2021-10-19'}, {y: '90', x: '2021-10-20'}, {y: '65', x: '2021-10-21'},
{y: '100', x: '2021-10-22'}, {y: '200', x: '2021-10-23'}, {y: '440', x: '2021-11-02'},
{y: '2185', x: '2021-11-03'}, {y: '1695', x: '2021-11-04'}, {y: '1095', x: '2021-11-08'},
{y: '1730', x: '2021-11-09'}, {y: '1905', x: '2021-11-10'}
]
[
{y: '20', x: '2021-10-14'}, {y: '520', x: '2021-10-15'}, {y: '1115', x: '2021-10-18'},
{y: '1035', x: '2021-10-19'}, {y: '900', x: '2021-10-20'}, {y: '655', x: '2021-10-21'},
{y: '510', x: '2021-10-22'}, {y: '65', x: '2021-10-24'}, {y: '1375', x: '2021-10-25'},
{y: '925', x: '2021-10-26'}, {y: '1240', x: '2021-10-27'}, {y: '855', x: '2021-10-28'},
{y: '640', x: '2021-11-02'}, {y: '218', x: '2021-11-03'}, {y: '1500', x: '2021-11-05'},
{y: '1010', x: '2021-11-08'}, {y: '1250', x: '2021-11-09'}, {y: '1905', x: '2021-11-10'} ]