Compare commits
3 commits
1f99528511
...
f6b4af7f04
Author | SHA1 | Date | |
---|---|---|---|
f6b4af7f04 | |||
146e3dd6c2 | |||
79399032d6 |
14 changed files with 118 additions and 30 deletions
Binary file not shown.
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 128 KiB |
|
@ -7,7 +7,7 @@
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta
|
<meta
|
||||||
name="description"
|
name="description"
|
||||||
content="Web site created using create-react-app"
|
content="Web site to view flowcharts of german speedclimbing competitions"
|
||||||
/>
|
/>
|
||||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||||
<!--
|
<!--
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
work correctly both with client-side routing and a non-root public URL.
|
work correctly both with client-side routing and a non-root public URL.
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
-->
|
-->
|
||||||
<title>React App</title>
|
<title>blueROCK speed-flowchart</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 46 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 170 KiB |
35
src/components/Header.tsx
Normal file
35
src/components/Header.tsx
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import {
|
||||||
|
AppBar,
|
||||||
|
Toolbar,
|
||||||
|
Stepper,
|
||||||
|
Step,
|
||||||
|
Box,
|
||||||
|
Container,
|
||||||
|
StepButton,
|
||||||
|
Typography,
|
||||||
|
} from '@mui/material';
|
||||||
|
import { useContext, useEffect, useState } from 'react';
|
||||||
|
import { Link, useLocation, useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import '../css/Header.css';
|
||||||
|
import { Context } from '../data/Context';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Header Component that displays the reservation steps
|
||||||
|
* @return {JSX.Element}
|
||||||
|
*/
|
||||||
|
export default function Header() {
|
||||||
|
const { title } = useContext(Context);
|
||||||
|
return (
|
||||||
|
<AppBar position='sticky'>
|
||||||
|
<Container maxWidth='lg'>
|
||||||
|
<Toolbar className='header-container'>
|
||||||
|
<Link to='/' style={{ textDecoration: 'none', color: 'inherit' }}>
|
||||||
|
<img src='/logo192.png' className='header-icon'></img>
|
||||||
|
</Link>
|
||||||
|
<Typography variant='h6'>{title}</Typography>
|
||||||
|
</Toolbar>
|
||||||
|
</Container>
|
||||||
|
</AppBar>
|
||||||
|
);
|
||||||
|
}
|
9
src/css/Header.css
Normal file
9
src/css/Header.css
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
.header-container {
|
||||||
|
gap: 40px;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-icon {
|
||||||
|
height: 50px;
|
||||||
|
display: block;
|
||||||
|
}
|
|
@ -7,6 +7,14 @@ import { DigitalrockAPi } from './DigitalrockApi';
|
||||||
*/
|
*/
|
||||||
export const Context = createContext<{
|
export const Context = createContext<{
|
||||||
api: DigitalrockAPi;
|
api: DigitalrockAPi;
|
||||||
|
|
||||||
|
title: string;
|
||||||
|
setTitle: (title: string) => void;
|
||||||
}>({
|
}>({
|
||||||
api: new DigitalrockAPi(),
|
api: new DigitalrockAPi(),
|
||||||
|
|
||||||
|
title: '',
|
||||||
|
setTitle: () => {
|
||||||
|
return;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -212,11 +212,12 @@ export function convertResultsToSpeedFlowchartResult(
|
||||||
// - 1, 4, 2, 3 for firstRoundNumber=4
|
// - 1, 4, 2, 3 for firstRoundNumber=4
|
||||||
// - 1, 2 for firstRoundNumber=2
|
// - 1, 2 for firstRoundNumber=2
|
||||||
// TODO: come up with a proper alogorithm maybe
|
// TODO: come up with a proper alogorithm maybe
|
||||||
|
console.log('First round rank: ', firstRoundRank);
|
||||||
const ranksOfLaneAInOrder = [
|
const ranksOfLaneAInOrder = [
|
||||||
[1, 2],
|
[1, 2],
|
||||||
[1, 4, 2, 3],
|
[1, 4, 2, 3],
|
||||||
[1, 8, 4, 5, 2, 7, 3, 6],
|
[1, 8, 4, 5, 2, 7, 3, 6],
|
||||||
][firstRoundRank / 4];
|
][Math.floor(firstRoundRank / 4)];
|
||||||
|
|
||||||
const firstRoundPairs = ranksOfLaneAInOrder.map(rank => {
|
const firstRoundPairs = ranksOfLaneAInOrder.map(rank => {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -5,9 +5,12 @@ export interface Competiton {
|
||||||
WetId: string;
|
WetId: string;
|
||||||
rkey: string;
|
rkey: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
comp_name: string;
|
||||||
date_span: string;
|
date_span: string;
|
||||||
discipline?: string;
|
discipline?: string;
|
||||||
cats: Category[];
|
cats: Category[];
|
||||||
|
categorys: Category[];
|
||||||
|
date: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RouteNames {
|
export interface RouteNames {
|
||||||
|
@ -25,4 +28,5 @@ export interface RouteNames {
|
||||||
export interface SpeedCompetitionCategoryResult extends Competiton {
|
export interface SpeedCompetitionCategoryResult extends Competiton {
|
||||||
route_names: RouteNames;
|
route_names: RouteNames;
|
||||||
participants: ParticipantFromApi[];
|
participants: ParticipantFromApi[];
|
||||||
|
route_order: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,13 @@ export default function CalendarPage() {
|
||||||
React.useState<Competiton[]>();
|
React.useState<Competiton[]>();
|
||||||
const [filter, setFilter] = React.useState<string>();
|
const [filter, setFilter] = React.useState<string>();
|
||||||
|
|
||||||
const { api } = React.useContext(Context);
|
const { api, setTitle } = React.useContext(Context);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
setTitle('DAV calendar');
|
||||||
|
}, []);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
api.getCompetitions('GER').then(result => {
|
api.getCompetitions('GER').then(result => {
|
||||||
console.log(result.competitions.filter);
|
console.log(result.competitions.filter);
|
||||||
|
@ -42,9 +46,14 @@ export default function CalendarPage() {
|
||||||
}, [filter]);
|
}, [filter]);
|
||||||
|
|
||||||
const filterCompetitions = (competitions: Competiton[]) => {
|
const filterCompetitions = (competitions: Competiton[]) => {
|
||||||
return competitions.filter(c =>
|
return competitions.filter(c => {
|
||||||
c.name.toLowerCase().includes(filter?.toLocaleLowerCase() ?? ''),
|
const queryMatches = c.name
|
||||||
);
|
.toLowerCase()
|
||||||
|
.includes(filter?.toLocaleLowerCase() ?? '');
|
||||||
|
const date = new Date(c.date).getTime();
|
||||||
|
const currentDate = new Date().getTime();
|
||||||
|
return queryMatches && currentDate - date > 24 * 60 * 60 * 1000;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const openCompetition = (competitionId: string, categoryId: string) => {
|
const openCompetition = (competitionId: string, categoryId: string) => {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { Card, CardContent, Grid, Typography } from '@mui/material';
|
||||||
*/
|
*/
|
||||||
export default function SpeedFlowchartPage() {
|
export default function SpeedFlowchartPage() {
|
||||||
const { competitionId, categoryId } = useParams();
|
const { competitionId, categoryId } = useParams();
|
||||||
const { api } = useContext(Context);
|
const { api, setTitle } = useContext(Context);
|
||||||
|
|
||||||
const [flowchartResult, setFlowchartResult] =
|
const [flowchartResult, setFlowchartResult] =
|
||||||
useState<SpeedFlowchartResult>();
|
useState<SpeedFlowchartResult>();
|
||||||
|
@ -24,6 +24,12 @@ export default function SpeedFlowchartPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
api.getCompetitionResults(competitionId, categoryId).then(r => {
|
api.getCompetitionResults(competitionId, categoryId).then(r => {
|
||||||
|
setTitle(
|
||||||
|
`${r.comp_name} - ${
|
||||||
|
r.categorys.filter(cat => cat.GrpId === categoryId)[0].name
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
|
||||||
const flowchartResult = convertResultsToSpeedFlowchartResult(r);
|
const flowchartResult = convertResultsToSpeedFlowchartResult(r);
|
||||||
console.log(flowchartResult);
|
console.log(flowchartResult);
|
||||||
setFlowchartResult(flowchartResult);
|
setFlowchartResult(flowchartResult);
|
||||||
|
@ -32,7 +38,6 @@ export default function SpeedFlowchartPage() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1>RESULT:</h1>
|
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
{flowchartResult?.rounds.map((round, roundKey) => (
|
{flowchartResult?.rounds.map((round, roundKey) => (
|
||||||
<Grid key={`flowchart-column-${roundKey}`} item xs={12 / 5}>
|
<Grid key={`flowchart-column-${roundKey}`} item xs={12 / 5}>
|
||||||
|
@ -71,6 +76,12 @@ export default function SpeedFlowchartPage() {
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
{flowchartResult === undefined && (
|
||||||
|
<Grid item xs={12} className={'center-children'}>
|
||||||
|
This competition or category does not have a speed tree!
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import React from 'react';
|
||||||
import { Context } from '../data/Context';
|
import { Context } from '../data/Context';
|
||||||
import { DigitalrockAPi } from '../data/DigitalrockApi';
|
import { DigitalrockAPi } from '../data/DigitalrockApi';
|
||||||
|
|
||||||
|
@ -10,6 +11,11 @@ export default function ContextWrapper(props: { children: JSX.Element }) {
|
||||||
const { children } = props;
|
const { children } = props;
|
||||||
|
|
||||||
const api = new DigitalrockAPi();
|
const api = new DigitalrockAPi();
|
||||||
|
const [title, setTitle] = React.useState('');
|
||||||
|
|
||||||
return <Context.Provider value={{ api }}>{children}</Context.Provider>;
|
return (
|
||||||
|
<Context.Provider value={{ api, title, setTitle }}>
|
||||||
|
{children}
|
||||||
|
</Context.Provider>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,16 +11,14 @@ export default function PageTemplate(props: { children: JSX.Element }) {
|
||||||
const { children } = props;
|
const { children } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContextWrapper>
|
|
||||||
<LocalizationProviderWrapper>
|
<LocalizationProviderWrapper>
|
||||||
<Container
|
<Container
|
||||||
sx={{ marginTop: '50px' }}
|
sx={{ marginTop: '16px' }}
|
||||||
className='root-container'
|
className='root-container'
|
||||||
maxWidth='lg'
|
maxWidth='lg'
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Container>
|
</Container>
|
||||||
</LocalizationProviderWrapper>
|
</LocalizationProviderWrapper>
|
||||||
</ContextWrapper>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { Routes, Route, HashRouter } from 'react-router-dom';
|
import { Routes, Route, HashRouter } from 'react-router-dom';
|
||||||
|
import Header from '../components/Header';
|
||||||
import CalendarPage from '../pages/CalendarPage';
|
import CalendarPage from '../pages/CalendarPage';
|
||||||
import SpeedFlowchartPage from '../pages/SpeedFlowchartPage';
|
import SpeedFlowchartPage from '../pages/SpeedFlowchartPage';
|
||||||
|
import ContextWrapper from './ContextWrapper';
|
||||||
import PageTemplate from './PageTemplate';
|
import PageTemplate from './PageTemplate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10,6 +12,9 @@ import PageTemplate from './PageTemplate';
|
||||||
export default function Routing() {
|
export default function Routing() {
|
||||||
return (
|
return (
|
||||||
<HashRouter>
|
<HashRouter>
|
||||||
|
<ContextWrapper>
|
||||||
|
<>
|
||||||
|
<Header />
|
||||||
<PageTemplate>
|
<PageTemplate>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path='/' element={<CalendarPage />} />
|
<Route path='/' element={<CalendarPage />} />
|
||||||
|
@ -19,6 +24,8 @@ export default function Routing() {
|
||||||
></Route>
|
></Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
</PageTemplate>
|
</PageTemplate>
|
||||||
|
</>
|
||||||
|
</ContextWrapper>
|
||||||
</HashRouter>
|
</HashRouter>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue