diff --git a/src/components/Bar.tsx b/src/components/Bar.tsx index 378a694..396fe7f 100644 --- a/src/components/Bar.tsx +++ b/src/components/Bar.tsx @@ -1,4 +1,3 @@ -import React from "react"; import styled from "styled-components"; import { ZoneType } from "zwiftout"; @@ -33,35 +32,33 @@ export const Bar = styled.div` `; export type RangeBarProps = { - startZone: ZoneType; - endZone: ZoneType; // Percentage of total workout length durationPercentage: number; // Percentage of maximum intensity in workout - intensityStartPercentage: number; - intensityEndPercentage: number; + maxIntensityPercentage: number; + // Percentage relative to `maxIntensityPercentage` + relativeMinIntensityPercentage: number; + startZone: ZoneType; + endZone: ZoneType; + direction: "up" | "down"; }; const createUpPolygon = (middle: number) => `polygon(0% 100%, 100% 100%, 100% 0%, 0% ${middle}%)`; const createDownPolygon = (middle: number) => `polygon(0% 0%, 0% 100%, 100% 100%, 100% ${middle}%)`; -export const RangeContainer = styled.div<{ - height: number; - width: number; - startZone: ZoneType; - endZone: ZoneType; - middle: number; - direction: "up" | "down"; -}>` +export const RangeBar = styled.div` display: inline-block; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; vertical-align: bottom; margin-right: 0.1%; /* exclude 0.1% margin from bar width */ - width: ${(props) => props.width - 0.1}%; - height: ${(props) => props.height}%; - clip-path: ${({ direction, middle }) => (direction === "up" ? createUpPolygon(middle) : createDownPolygon(middle))}; + width: ${(props) => props.durationPercentage - 0.1}%; + height: ${(props) => props.maxIntensityPercentage}%; + clip-path: ${({ direction, relativeMinIntensityPercentage }) => + direction === "up" + ? createUpPolygon(relativeMinIntensityPercentage) + : createDownPolygon(relativeMinIntensityPercentage)}; background: linear-gradient( to right, ${(props) => zoneColorsMap[props.startZone]}, @@ -69,22 +66,3 @@ export const RangeContainer = styled.div<{ ); transition: width 0.1s, height 0.1s, background-color 0.1s; `; - -export const RangeBar: React.FC = (props) => { - const minHeightPercentage = Math.min(props.intensityStartPercentage, props.intensityEndPercentage); - const maxHeightPercentage = Math.max(props.intensityStartPercentage, props.intensityEndPercentage); - const bottomHeight = (minHeightPercentage / maxHeightPercentage) * 100; - const topHeight = 100 - bottomHeight; - const direction = props.intensityStartPercentage < props.intensityEndPercentage ? "up" : "down"; - - return ( - - ); -}; diff --git a/src/components/WorkoutPlot.tsx b/src/components/WorkoutPlot.tsx index 02d0bd1..6409480 100644 --- a/src/components/WorkoutPlot.tsx +++ b/src/components/WorkoutPlot.tsx @@ -26,13 +26,21 @@ const Plot = styled.div` margin: 10px 0; `; -const toRangeBarProps = (interval: Interval, workoutDuration: Duration, maxIntensity: Intensity): RangeBarProps => ({ - startZone: intensityValueToZoneType(interval.intensity.start), - endZone: intensityValueToZoneType(interval.intensity.end), - durationPercentage: (interval.duration.seconds / workoutDuration.seconds) * 100, - intensityStartPercentage: (interval.intensity.start / maxIntensity.value) * 100, - intensityEndPercentage: (interval.intensity.end / maxIntensity.value) * 100, -}); +const toRangeBarProps = (interval: Interval, workoutDuration: Duration, maxIntensity: Intensity): RangeBarProps => { + const minIntensityPercentage = + (Math.min(interval.intensity.start, interval.intensity.end) / maxIntensity.value) * 100; + const maxIntensityPercentage = + (Math.max(interval.intensity.start, interval.intensity.end) / maxIntensity.value) * 100; + + return { + durationPercentage: (interval.duration.seconds / workoutDuration.seconds) * 100, + maxIntensityPercentage: maxIntensityPercentage, + relativeMinIntensityPercentage: 100 - (minIntensityPercentage / maxIntensityPercentage) * 100, + direction: interval.intensity.start < interval.intensity.end ? "up" : "down", + startZone: intensityValueToZoneType(interval.intensity.start), + endZone: intensityValueToZoneType(interval.intensity.end), + }; +}; export const WorkoutPlot: React.FC<{ intervals: Interval[] }> = ({ intervals }) => { const workoutDuration = totalDuration(intervals);