Improved overall styling
This commit is contained in:
parent
481ae9c8a7
commit
e528910ac9
16
src/App.tsx
16
src/App.tsx
|
|
@ -3,6 +3,7 @@ import { WorkoutPlot } from './components/WorkoutPlot';
|
||||||
import { WorkoutStats } from './components/WorkoutStats';
|
import { WorkoutStats } from './components/WorkoutStats';
|
||||||
import { parse, chunkRangeIntervals, Duration } from 'make-workout';
|
import { parse, chunkRangeIntervals, Duration } from 'make-workout';
|
||||||
import { ErrorMessage } from './components/ErrorMessage';
|
import { ErrorMessage } from './components/ErrorMessage';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
const defaultWorkout = `Name: Hello
|
const defaultWorkout = `Name: Hello
|
||||||
|
|
||||||
|
|
@ -14,6 +15,15 @@ FreeRide: 10:00
|
||||||
Cooldown: 10:00 60%..30%
|
Cooldown: 10:00 60%..30%
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const AppContainer = styled.div`
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const AppTitle = styled.h1`
|
||||||
|
font-weight: normal;
|
||||||
|
`;
|
||||||
|
|
||||||
// Split range-intervals into 1 minute chunks
|
// Split range-intervals into 1 minute chunks
|
||||||
const chunkSize = new Duration(60);
|
const chunkSize = new Duration(60);
|
||||||
|
|
||||||
|
|
@ -34,12 +44,12 @@ export function App() {
|
||||||
}, [setText, setWorkout, setError]);
|
}, [setText, setWorkout, setError]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<AppContainer>
|
||||||
<h1>Workout editor</h1>
|
<AppTitle>Workout editor</AppTitle>
|
||||||
<textarea rows={10} cols={100} onChange={onChange} value={text} />
|
<textarea rows={10} cols={100} onChange={onChange} value={text} />
|
||||||
<WorkoutPlot intervals={chunkRangeIntervals(workout.intervals, chunkSize)} />
|
<WorkoutPlot intervals={chunkRangeIntervals(workout.intervals, chunkSize)} />
|
||||||
{error && <ErrorMessage>{error}</ErrorMessage>}
|
{error && <ErrorMessage>{error}</ErrorMessage>}
|
||||||
<WorkoutStats workout={workout} />
|
<WorkoutStats workout={workout} />
|
||||||
</div>
|
</AppContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,7 @@ const toBarProps = (interval: Interval, workoutDuration: Duration, maxIntensity:
|
||||||
const Plot = styled.div`
|
const Plot = styled.div`
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 800px;
|
|
||||||
height: 200px;
|
height: 200px;
|
||||||
background: rgba(0,0,0, 0.03);
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { stats, Workout, Intensity } from 'make-workout';
|
import { stats, Workout, Intensity } from 'make-workout';
|
||||||
import { formatDuration } from './formatDuration';
|
import { formatDuration } from './formatDuration';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
const formatIntensity = (intensity: Intensity): string => `${Math.round(intensity.value * 100)}%`;
|
const formatIntensity = (intensity: Intensity): string => `${Math.round(intensity.value * 100)}%`;
|
||||||
|
|
||||||
|
|
@ -8,22 +9,53 @@ const StatsLine: React.FC<{ label: string, value: string | number }> = ({ label,
|
||||||
<li><strong>{label}</strong> {value}</li>
|
<li><strong>{label}</strong> {value}</li>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 3fr;
|
||||||
|
border: 1px solid #bbb;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
background: rgba(255, 255, 255, 0.6);
|
||||||
|
`;
|
||||||
|
const Section = styled.section``;
|
||||||
|
|
||||||
|
const Header = styled.h2`
|
||||||
|
margin: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: normal;
|
||||||
|
`;
|
||||||
|
const List = styled.ul`
|
||||||
|
margin: 1m 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
`;
|
||||||
|
const ZoneList = styled(List)`
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
`;
|
||||||
|
|
||||||
|
|
||||||
export const WorkoutStats: React.FC<{workout: Workout}> = ({ workout }) => {
|
export const WorkoutStats: React.FC<{workout: Workout}> = ({ workout }) => {
|
||||||
const {totalDuration, averageIntensity, normalizedIntensity, tss, zones} = stats(workout);
|
const {totalDuration, averageIntensity, normalizedIntensity, tss, zones} = stats(workout);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<Container>
|
||||||
<h2>Summary</h2>
|
<Section>
|
||||||
<ul>
|
<Header>Summary</Header>
|
||||||
|
<List>
|
||||||
<StatsLine label="Duration:" value={formatDuration(totalDuration)} />
|
<StatsLine label="Duration:" value={formatDuration(totalDuration)} />
|
||||||
<StatsLine label="Average intensity:" value={formatIntensity(averageIntensity)} />
|
<StatsLine label="Average intensity:" value={formatIntensity(averageIntensity)} />
|
||||||
<StatsLine label="Normalized intensity:" value={formatIntensity(normalizedIntensity)} />
|
<StatsLine label="Normalized intensity:" value={formatIntensity(normalizedIntensity)} />
|
||||||
<StatsLine label="TSS:" value={Math.round(tss)} />
|
<StatsLine label="TSS:" value={Math.round(tss)} />
|
||||||
</ul>
|
</List>
|
||||||
<h2>Zone distribution</h2>
|
</Section>
|
||||||
<ul>
|
<Section>
|
||||||
|
<Header>Zone distribution</Header>
|
||||||
|
<ZoneList>
|
||||||
{zones.map(zone => (<StatsLine label={zone.name} value={formatDuration(zone.duration)} />)) }
|
{zones.map(zone => (<StatsLine label={zone.name} value={formatDuration(zone.duration)} />)) }
|
||||||
</ul>
|
</ZoneList>
|
||||||
</div>
|
</Section>
|
||||||
|
</Container>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 40px;
|
padding: 40px;
|
||||||
background-color: #f5f5e5;
|
background-color: #f7f7f2;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||||
sans-serif;
|
sans-serif;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue