54 lines
2.2 KiB
TypeScript
54 lines
2.2 KiB
TypeScript
'use client';
|
|
import { LineChart, Line, YAxis, XAxis, CartesianGrid, Tooltip, Area, Label } from 'recharts';
|
|
import spacetime from 'spacetime';
|
|
import regression from 'regression';
|
|
|
|
function polynomialTrendline(data, degree) {
|
|
// Map your data to the form required by regression-js: [x, y]
|
|
// Here we convert datetime to a numeric value (e.g., milliseconds since epoch)
|
|
const regressionData = data.map((dp, i) => [i, dp.value]);
|
|
|
|
const result = regression.polynomial(regressionData, { order: degree });
|
|
// result.equation contains the polynomial coefficients,
|
|
// and result.predict(x) returns the predicted y for a given x value.
|
|
return result;
|
|
}
|
|
|
|
function formatXAxis(tickItem) {
|
|
return spacetime(tickItem).format('{date}');
|
|
}
|
|
|
|
export default function TimeseriesChart({ data }) {
|
|
const unit = data[0] ? data[0].unit : '';
|
|
|
|
const polyResult = polynomialTrendline(data, 1)// 2 for quadratic
|
|
const dataWithFit = (data.map((dp, i) => {
|
|
return {
|
|
datetime: dp.datetime,
|
|
value: dp.value,
|
|
smoothed: polyResult.predict(i)[1],
|
|
};
|
|
}));
|
|
console.log(polyResult);
|
|
|
|
return (
|
|
<div className='flex flex-col items-center'>
|
|
<h2>
|
|
Trend: {7 * polyResult.equation[0]} {unit}/week
|
|
</h2>
|
|
<LineChart width={800} height={400} data={dataWithFit}>
|
|
<CartesianGrid stroke="#999" strokeDasharray="1 5" />
|
|
<Tooltip
|
|
label="test"
|
|
labelFormatter={(d) => `${spacetime(d).format("{month-short} {date}")}`}
|
|
labelStyle={{ color: 'black' }}
|
|
/>
|
|
<XAxis dataKey="datetime" tickFormatter={formatXAxis} tickMargin={10} />
|
|
<YAxis unit={` ${unit}`} width={120} domain={['dataMin - 10', 'dataMax']} />
|
|
<Line type="natural" dataKey="value" stroke="white" activeDot={{ stroke: 'pink', strokeWidth: 2, r: 5 }} dot={{ fill: 'red', stroke: 'red', strokeWidth: 1 }} />
|
|
|
|
<Line type="natural" dataKey="smoothed" stroke={polyResult.equation[0] > 0 ? "red" : "green"} dot={false} />
|
|
</LineChart>
|
|
</div>
|
|
);
|
|
}
|