Skip to content

Commit

Permalink
Merge pull request #520 from openclimatefix/issue/519-india-X-forecast
Browse files Browse the repository at this point in the history
Issue/519 india x forecast
  • Loading branch information
braddf authored Jun 19, 2024
2 parents 932e2e7 + 8c979ec commit e776bae
Show file tree
Hide file tree
Showing 11 changed files with 362 additions and 61 deletions.
14 changes: 14 additions & 0 deletions apps/quartz-app/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,17 @@ body {
text-wrap: balance;
}
}

.fade-out {
opacity: 1;
animation: fade-out 2s ease-in-out forwards;
}

@keyframes fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
59 changes: 59 additions & 0 deletions apps/quartz-app/src/components/InfoTooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
type TooltipProps = {
children: React.ReactNode;
tip: string | React.ReactNode;
position?: "left" | "right" | "middle" | "top";
className?: string;
fullWidth?: boolean;
};

const Tooltip: React.FC<TooltipProps> = ({
children,
tip,
position,
className,
fullWidth = false,
}) => {
let containerPositionClass = "";
let tipPositionClass = "";
switch (position) {
case "left":
containerPositionClass = "right-1";
tipPositionClass = "-right-1 top-2";
break;
case "right":
containerPositionClass = "left-1";
tipPositionClass = "-left-1 top-2";
break;
// case "middle":
// containerPositionClass = "right-5";
// // containerPositionClass = "left-1/2 transform -translate-x-1/2";
// tipPositionClass = "-right-1 top-0";
// break;
// case "top":
// containerPositionClass = "bottom-5 right-2";
// tipPositionClass = "-right-2 bottom-0";
}
return (
<div
className={`relative flex flex-col group z-20 ${
fullWidth ? "w-full" : "w-max items-center"
}
${className || ""}`}
>
{position !== "top" && children}
<div
className={`absolute flex-col items-center hidden mt-6 group-hover:flex w-fit ${containerPositionClass}`}
>
<span
className={`absolute ${tipPositionClass} mb-1 z-30 p-2 text-xs leading-none text-white whitespace-no-wrap bg-ocf-black shadow-lg rounded-md`}
>
{tip}
</span>
{/*<div className="w-3 h-5 -mt-[6px] rotate-45 bg-ocf-black "></div>*/}
</div>
{position === "top" && children}
</div>
);
};

export default Tooltip;
106 changes: 76 additions & 30 deletions apps/quartz-app/src/components/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,39 +13,63 @@ import { useEffect, useMemo } from "react";

export const Main = () => {
const [combinedData, setCombinedData] = useGlobalState("combinedData");
const [forecastHorizon] = useGlobalState("forecastHorizon");
const [forecastHorizonMinutes] = useGlobalState("forecastHorizonMinutes");

const { data: solarRegionsData, error: solarRegionsError } =
useGetRegionsQuery("solar");
const {
data: solarRegionsData,
isLoading: solarRegionsLoading,
error: solarRegionsError,
} = useGetRegionsQuery("solar");

const { data: windRegionsData, error: windRegionsError } =
useGetRegionsQuery("wind");
const {
data: windRegionsData,
isLoading: windRegionsLoading,
error: windRegionsError,
} = useGetRegionsQuery("wind");

const { data: solarGenerationData, error: solarGenerationError } =
useGetGenerationForRegionQuery(
"solar",
solarRegionsData?.regions[0] || "",
!!solarRegionsData?.regions[0]
);
const { data: windGenerationData, error: windGenerationError } =
useGetGenerationForRegionQuery(
"wind",
windRegionsData?.regions[0] || "",
!!windRegionsData?.regions[0]
);
const {
data: solarGenerationData,
isLoading: solarGenerationLoading,
error: solarGenerationError,
} = useGetGenerationForRegionQuery(
"solar",
solarRegionsData?.regions[0] || "",
!!solarRegionsData?.regions[0]
);
const {
data: windGenerationData,
isLoading: windGenerationLoading,
error: windGenerationError,
} = useGetGenerationForRegionQuery(
"wind",
windRegionsData?.regions[0] || "",
!!windRegionsData?.regions[0]
);

// Get forecast data
const { data: solarForecastData, error: solarForecastError } =
useGetForecastedGenerationForRegionQuery(
"solar",
solarRegionsData?.regions[0] || "",
!!solarRegionsData?.regions[0]
);
const { data: windForecastData, error: windForecastError } =
useGetForecastedGenerationForRegionQuery(
"wind",
windRegionsData?.regions[0] || "",
!!windRegionsData?.regions[0]
);
const {
data: solarForecastData,
isLoading: solarForecastLoading,
error: solarForecastError,
} = useGetForecastedGenerationForRegionQuery(
"solar",
solarRegionsData?.regions[0] || "",
!!solarRegionsData?.regions[0],
forecastHorizon,
forecastHorizonMinutes
);
const {
data: windForecastData,
isLoading: windForecastLoading,
error: windForecastError,
} = useGetForecastedGenerationForRegionQuery(
"wind",
windRegionsData?.regions[0] || "",
!!windRegionsData?.regions[0],
forecastHorizon,
forecastHorizonMinutes
);

const latestCombinedData: CombinedData = useMemo(() => {
return {
Expand All @@ -66,6 +90,24 @@ export const Main = () => {
setCombinedData(latestCombinedData);
}, [latestCombinedData]);

const isLoading = useMemo(() => {
return (
solarForecastLoading ||
windForecastLoading ||
solarGenerationLoading ||
windGenerationLoading ||
solarRegionsLoading ||
windRegionsLoading
);
}, [
solarForecastLoading,
windForecastLoading,
solarGenerationLoading,
windGenerationLoading,
solarRegionsLoading,
windRegionsLoading,
]);

if (
solarRegionsError ||
windRegionsError ||
Expand All @@ -83,7 +125,11 @@ export const Main = () => {
solarForecastError,
windForecastError
);
return <div>Error</div>;
return (
<div className="text-white flex items-center justify-center absolute inset-0">
An error has occurred. Please refresh, or try again shortly.
</div>
);
}

return (
Expand All @@ -95,7 +141,7 @@ export const Main = () => {
solarGenerationData={solarGenerationData}
windGenerationData={windGenerationData}
/>
<Charts combinedData={combinedData} />
<Charts combinedData={combinedData} isLoading={isLoading} />
</>
);
};
31 changes: 28 additions & 3 deletions apps/quartz-app/src/components/charts/Charts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@ import {
} from "recharts";
// @ts-ignore
import { theme } from "@/tailwind.config";
import { FC, ReactNode } from "react";
import { ChangeEvent, FC, useEffect } from "react";
import {
ACTUAL_SOLAR_COLOR,
ACTUAL_WIND_COLOR,
SOLAR_COLOR,
WIND_COLOR,
} from "@/src/constants";
import { LegendContainer } from "@/src/components/charts/legend/LegendContainer";
import {
formatEpochToHumanDayName,
formatEpochToPrettyTime,
Expand All @@ -32,12 +31,15 @@ import { useChartData } from "@/src/hooks/useChartData";
import { CustomLabel } from "@/src/components/charts/labels/CustomLabel";
import { useGlobalState } from "../helpers/globalState";
import { DateTime } from "luxon";
import { Spinner, SpinnerTextInline } from "@/src/components/icons/icons";
import HorizonSelect from "@/src/components/charts/HorizonSelect";

type ChartsProps = {
combinedData: CombinedData;
isLoading: boolean;
};

const Charts: FC<ChartsProps> = ({ combinedData }) => {
const Charts: FC<ChartsProps> = ({ combinedData, isLoading }) => {
const { data, error } = useGetRegionsQuery("solar");
console.log("Charts data test", data);
const formattedChartData = useChartData(combinedData);
Expand Down Expand Up @@ -70,6 +72,22 @@ const Charts: FC<ChartsProps> = ({ combinedData }) => {

return (
<div className="flex-1 flex flex-col justify-center items-center bg-ocf-grey-800">
<div className="flex flex-1 w-full items-center justify-between -mb-6 py-3 px-4">
<div className="flex">
{isLoading ? (
<div className="pointer-events-none text-white px-2.5 py-0.5 rounded-md bg-ocf-black flex items-center gap-2">
Loading data <SpinnerTextInline />
</div>
) : (
<div className="fade-out pointer-events-none text-white px-2.5 py-0.5 rounded-md bg-ocf-black flex items-center">
Data loaded
</div>
)}
</div>
<div className="flex gap-5">
<HorizonSelect />
</div>
</div>
<div style={{ position: "relative", width: "100%", height: "100%" }}>
{/* Helps with the resizing of the chart in both axes */}
<div
Expand All @@ -81,6 +99,13 @@ const Charts: FC<ChartsProps> = ({ combinedData }) => {
top: 0,
}}
>
{isLoading && (
<div
className={`absolute flex pb-7 items-center justify-center inset-0 z-30`}
>
<Spinner className="w-10 h-10 fill-ocf-yellow text-ocf-grey-700" />
</div>
)}
<ResponsiveContainer>
<ComposedChart
data={formattedChartData}
Expand Down
Loading

0 comments on commit e776bae

Please sign in to comment.