Refactor RangeBar to just a simple styled component

This commit is contained in:
Rene Saarsoo 2020-11-23 05:15:41 +02:00
parent 73d7852309
commit eea49adfee
2 changed files with 28 additions and 42 deletions

View File

@ -1,4 +1,3 @@
import React from "react";
import styled from "styled-components"; import styled from "styled-components";
import { ZoneType } from "zwiftout"; import { ZoneType } from "zwiftout";
@ -33,35 +32,33 @@ export const Bar = styled.div<BarProps>`
`; `;
export type RangeBarProps = { export type RangeBarProps = {
startZone: ZoneType;
endZone: ZoneType;
// Percentage of total workout length // Percentage of total workout length
durationPercentage: number; durationPercentage: number;
// Percentage of maximum intensity in workout // Percentage of maximum intensity in workout
intensityStartPercentage: number; maxIntensityPercentage: number;
intensityEndPercentage: 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 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}%)`; const createDownPolygon = (middle: number) => `polygon(0% 0%, 0% 100%, 100% 100%, 100% ${middle}%)`;
export const RangeContainer = styled.div<{ export const RangeBar = styled.div<RangeBarProps>`
height: number;
width: number;
startZone: ZoneType;
endZone: ZoneType;
middle: number;
direction: "up" | "down";
}>`
display: inline-block; display: inline-block;
border-bottom-left-radius: 10px; border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px; border-bottom-right-radius: 10px;
vertical-align: bottom; vertical-align: bottom;
margin-right: 0.1%; margin-right: 0.1%;
/* exclude 0.1% margin from bar width */ /* exclude 0.1% margin from bar width */
width: ${(props) => props.width - 0.1}%; width: ${(props) => props.durationPercentage - 0.1}%;
height: ${(props) => props.height}%; height: ${(props) => props.maxIntensityPercentage}%;
clip-path: ${({ direction, middle }) => (direction === "up" ? createUpPolygon(middle) : createDownPolygon(middle))}; clip-path: ${({ direction, relativeMinIntensityPercentage }) =>
direction === "up"
? createUpPolygon(relativeMinIntensityPercentage)
: createDownPolygon(relativeMinIntensityPercentage)};
background: linear-gradient( background: linear-gradient(
to right, to right,
${(props) => zoneColorsMap[props.startZone]}, ${(props) => zoneColorsMap[props.startZone]},
@ -69,22 +66,3 @@ export const RangeContainer = styled.div<{
); );
transition: width 0.1s, height 0.1s, background-color 0.1s; transition: width 0.1s, height 0.1s, background-color 0.1s;
`; `;
export const RangeBar: React.FC<RangeBarProps> = (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 (
<RangeContainer
height={maxHeightPercentage}
width={props.durationPercentage}
middle={topHeight}
direction={direction}
startZone={props.startZone}
endZone={props.endZone}
/>
);
};

View File

@ -26,13 +26,21 @@ const Plot = styled.div`
margin: 10px 0; margin: 10px 0;
`; `;
const toRangeBarProps = (interval: Interval, workoutDuration: Duration, maxIntensity: Intensity): RangeBarProps => ({ 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), startZone: intensityValueToZoneType(interval.intensity.start),
endZone: intensityValueToZoneType(interval.intensity.end), 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,
});
export const WorkoutPlot: React.FC<{ intervals: Interval[] }> = ({ intervals }) => { export const WorkoutPlot: React.FC<{ intervals: Interval[] }> = ({ intervals }) => {
const workoutDuration = totalDuration(intervals); const workoutDuration = totalDuration(intervals);