Add state persistance function

This commit is contained in:
Florian Schroedl
2024-01-23 15:42:52 +01:00
parent 15033f6131
commit 3e32a7b122
6 changed files with 70 additions and 57 deletions

View File

@@ -16,6 +16,7 @@
"clsx": "^2.1.0", "clsx": "^2.1.0",
"date-fns": "^3.3.1", "date-fns": "^3.3.1",
"lucide-react": "^0.312.0", "lucide-react": "^0.312.0",
"ramda": "^0.29.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"recharts": "^2.10.4", "recharts": "^2.10.4",

View File

@@ -2,68 +2,31 @@ import React, { useState, useEffect } from "react";
import { LineChart, Line, CartesianGrid, XAxis, YAxis } from "recharts"; import { LineChart, Line, CartesianGrid, XAxis, YAxis } from "recharts";
import { format, addDays } from "date-fns"; import { format, addDays } from "date-fns";
import { Dashboard } from "@/components/main/routes/Dashboard"; import { Dashboard } from "@/components/main/routes/Dashboard";
import {
loadStorageOrDefault,
persistStorage,
} from "@/components/main/lib/state";
import { mergeDeepRight } from "ramda";
const formatDate = function (dateTime) { const STORAGE_KEY = "ecoplanet";
return format(dateTime, "yyyy-MM-dd");
};
const fetchWeekForecastData = async function (dateTime, cb) {
const formattedDate = formatDate(dateTime);
const forecastRequests = Array.from({ length: 7 }).map((_, index) => {
const date = addDays(dateTime, index);
const formattedDate = format(date, "yyyy-MM-d");
const url = `http://api.weatherapi.com/v1/future.json?key=bfca7632f8dc4253859120435242301&q=Vienna&dt=${formattedDate}`;
const dataPromise = fetch(url).then((x) => x.json());
return dataPromise;
});
const data = await Promise.all(forecastRequests);
console.log(data);
const chartData = data.map((forecastData) => {
const dayData = forecastData.forecast.forecastday[0];
const date = dayData.date;
const { avgtemp_c, mintemp_c, maxtemp_c } = dayData.day;
return {
name: date,
avgtemp_c,
mintemp_c,
maxtemp_c,
};
});
cb(chartData);
};
const WeatherChart = function ({ data }) {
return (
<LineChart width={400} height={400} data={data}>
<Line type="monotone" dataKey="avgtemp_c" stroke="#8884d8" />
<Line type="monotone" dataKey="mintemp_c" stroke="#8884d8" />
<Line type="monotone" dataKey="maxtemp_c" stroke="#8884d8" />
<CartesianGrid stroke="#ccc" />
<XAxis dataKey="name" />
<YAxis />
</LineChart>
);
};
const App: React.FC = () => { const App: React.FC = () => {
const [options, setOptions] = useState({ const [state, setState] = useState(loadStorageOrDefault);
lineWidth: undefined,
defaultDate: undefined, useEffect(() => {
}); persistStorage(state);
}, [state]);
const updateState = function (newState) {
setState(mergeDeepRight(state, newState));
};
return ( return (
<div className="fixed top-0 right-0 bottom-0 left-0 flex"> <div className="fixed top-0 right-0 bottom-0 left-0 flex">
<main className="flex grow flex-col"> <main className="flex grow flex-col">
<nav className="flex p-3 border-b border-solid border-slate-300"></nav> <nav className="flex p-3 border-b border-solid border-slate-300"></nav>
<div className="flex grow items-center justify-center h-full w-full"> <div className="flex grow items-center justify-center h-full w-full">
<Dashboard startDate={options.defaultDate} /> <Dashboard state={state} updateState={updateState} />
</div> </div>
</main> </main>
</div> </div>

View File

@@ -0,0 +1,36 @@
import { modifyPath, mergeDeepRight } from "ramda";
const STORAGE_KEY = "ecoplanet";
const defaultState = {
dateCache: undefined,
options: {
lineWidth: undefined,
defaultDate: undefined,
},
};
const stringifyState = function (state) {
return JSON.stringify(state);
};
const parseState = function (jsonString) {
const state = JSON.parse(jsonString);
return modifyPath(["options", "defaultDate"], Date.parse, state);
};
export const persistStorage = function (state) {
localStorage.setItem(STORAGE_KEY, stringifyState(state));
};
export const loadStorage = function () {
const storageStateString = localStorage.getItem(STORAGE_KEY);
if (storageStateString) {
return parseState(storageStateString);
}
};
export const loadStorageOrDefault = function (state) {
return mergeDeepRight(loadStorage(), defaultState);
};

View File

@@ -52,8 +52,10 @@ const WeatherChart = function ({ data }) {
); );
}; };
export const Dashboard = function ({ startDate = new Date() }) { export const Dashboard = function ({ state, updateCache }) {
const [dateTime, setDateTime] = useState(minDate(startDate)); const [dateTime, setDateTime] = useState(
minDate(state?.options?.startDate || new Date()),
);
const [data, setData] = useState(null); const [data, setData] = useState(null);
useEffect(() => { useEffect(() => {

View File

@@ -1,8 +1,14 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { format, addDays } from "date-fns"; import { parse, format, addDays } from "date-fns";
const DATE_FORMAT = "yyyy-MM-dd";
const parseDate = function (dateTime) {
return parse(dateTime, DATE_FORMAT);
};
export const formatDate = function (dateTime) { export const formatDate = function (dateTime) {
return format(dateTime, "yyyy-MM-dd"); return format(dateTime, DATE_FORMAT);
}; };
export const minDate = function (dateTime) { export const minDate = function (dateTime) {

View File

@@ -1982,6 +1982,11 @@ queue-microtask@^1.2.2:
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
ramda@^0.29.1:
version "0.29.1"
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.29.1.tgz#408a6165b9555b7ba2fc62555804b6c5a2eca196"
integrity sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==
react-dom@^18.2.0: react-dom@^18.2.0:
version "18.2.0" version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"