Skip to content

Commit

Permalink
implemented basic match preview default screen
Browse files Browse the repository at this point in the history
  • Loading branch information
kyle-flynn committed Apr 10, 2024
1 parent 15b76d2 commit 9ead9f3
Show file tree
Hide file tree
Showing 7 changed files with 316 additions and 8 deletions.
4 changes: 3 additions & 1 deletion front-end/src/api/use-event-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ export const useEvents = (): SWRResponse<Event[], ApiResponseError> =>
apiFetcher(url, 'GET', undefined, eventZod.array().parse)
);

export const useEvent = (eventKey?: string): SWRResponse<Event> =>
export const useEvent = (
eventKey: string | null | undefined
): SWRResponse<Event> =>
useSWRImmutable<Event>(
eventKey && eventKey.length > 0 ? `event/${eventKey}` : undefined,
(url) => apiFetcher(url, 'GET', undefined, eventZod.parse)
Expand Down
12 changes: 10 additions & 2 deletions front-end/src/apps/audience-display/displays/ad-default.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { FC } from 'react';
import { DisplayProps } from 'src/apps/audience-display/displays';
import { MatchPreview } from './seasons/frc_default/match-preview';
import { useRecoilValue } from 'recoil';
import { matchOccurringAtom } from 'src/stores/recoil';
import { useEvent } from 'src/api/use-event-data';

/**
* Classic audience display that handles all scenarios.
*/
export const AudDisplayDefault: FC<DisplayProps> = () => {
return null;
export const AudDisplayDefault: FC<DisplayProps> = ({ eventKey }) => {
// TODO - Is this how we want to handle the data flow?
// TODO - Get rankings for teams in the match
const { data: event } = useEvent(eventKey);
const match = useRecoilValue(matchOccurringAtom);
return match && event ? <MatchPreview event={event} match={match} /> : null;
};
11 changes: 6 additions & 5 deletions front-end/src/apps/audience-display/displays/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { AudDisplayStream } from './ad-stream';

export interface DisplayProps {
id: number;
eventKey: string | null | undefined;
}

interface Props {
Expand All @@ -14,16 +15,16 @@ interface Props {
mode?: DisplayModes;
}

const Displays: FC<Props> = ({ id, mode = DisplayModes.DEFAULT }) => {
const Displays: FC<Props> = ({ id, mode = DisplayModes.DEFAULT, eventKey }) => {
switch (mode) {
case DisplayModes.DEFAULT:
return <AudDisplayDefault id={id} />;
return <AudDisplayDefault id={id} eventKey={eventKey} />;
case DisplayModes.TIMER_ONLY:
return <AudDisplayTimer id={id} />;
return <AudDisplayTimer id={id} eventKey={eventKey} />;
case DisplayModes.STREAM:
return <AudDisplayStream id={id} />;
return <AudDisplayStream id={id} eventKey={eventKey} />;
default:
return <AudDisplayDefault id={id} />;
return <AudDisplayDefault id={id} eventKey={eventKey} />;
}
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import styled from '@emotion/styled';
import {
Alliance,
BLUE_STATION,
MatchParticipant,
Ranking,
Team
} from '@toa-lib/models';
import { FC } from 'react';

const Container = styled.div((props: { alliance: Alliance; size: number }) => ({
width: '100%',
backgroundColor: props.alliance === 'red' ? '#830E12' : '#004172',
display: 'grid',
gridTemplateRows: `repeat(${props.size + 1}, 1fr)`,
padding: '16px 32px 10vh 32px'
}));

const AllianceHeader = styled.div`
color: #ffffff;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
font-size: 2.25vw;
& > div {
background-color: #ffffff;
}
`;

const TeamContainer = styled.div`
display: flex;
justify-content: center;
align-items: center;
`;

const TeamRow = styled.div`
width: 35vw;
height: 12vh;
background-color: #ffffff;
box-shadow: -4px 4px 4px -2px rgba(0, 0, 0, 0.5);
display: grid;
grid-template-rows: 1fr 1fr;
font-size: 1.5vw;
font-weight: bold;
`;

const TeamHeader = styled.div((props: { alliance: Alliance }) => ({
height: '100%',
color: '#ffffff',
backgroundColor: props.alliance === 'red' ? '#ed1c24' : '#0066B3',
paddingLeft: '16px',
display: 'flex',
'& > div': {
display: 'flex',
alignItems: 'center'
}
}));

const TeamKey = styled.div`
width: 100%;
`;

const TeamRank = styled.div`
background-color: #101820;
height: 6vh;
width: 6vh;
justify-content: center;
`;

const TeamName = styled.div`
height: 100%;
color: #000000;
padding-left: 16px;
`;

interface AllianceProps {
alliance: Alliance;
team?: Team;
ranking?: Ranking;
}

// TODO - Handle display for team yellow card
const AllianceTeam: FC<AllianceProps> = ({ alliance, team, ranking }) => {
return (
<TeamContainer>
<TeamRow>
<TeamHeader alliance={alliance}>
<TeamKey>Team&nbsp;{team?.teamKey}</TeamKey>
{ranking && <TeamRank>{ranking.rank}</TeamRank>}
</TeamHeader>
<TeamName>{team?.teamNameShort}</TeamName>
</TeamRow>
</TeamContainer>
);
};

interface Props {
alliance: Alliance;
participants: MatchParticipant[];
}

export const MatchAlliancePreview: FC<Props> = ({ alliance, participants }) => {
const title = `${alliance} alliance`.toUpperCase();
const allianceParticipants = participants.filter((p) =>
alliance === 'red' ? p.station < BLUE_STATION : p.station >= BLUE_STATION
);
return (
<Container alliance={alliance} size={allianceParticipants.length}>
<AllianceHeader>{title}</AllianceHeader>
{allianceParticipants.map((p) => (
<AllianceTeam key={p.station} alliance={alliance} team={p.team} />
))}
</Container>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import styled from '@emotion/styled';
import { FC } from 'react';

const Container = styled.div`
transition: all 0.5s ease;
// top: -6.5vh;
position: relative;
z-index: 1;
`;

const Top = styled.div`
width: 100vw;
overflow: hidden;
height: 100%;
background-color: #ffffff;
color: #101820;
font-weight: bold;
font-size: 1.75vw;
display: flex;
justify-content: center;
align-items: center;
`;

const LeftContent = styled.div`
width: 15vw;
height: 100%;
padding-left: 10px;
display: flex;
justify-content: center;
align-items: center;
background-color: #101820;
`;

const CenterContent = styled.div`
width: 70vw;
height: 100%;
padding-left: 20px;
display: flex;
justify-content: flex-start;
align-items: center;
`;

const RightContent = styled.div`
width: 15vw;
height: 100%;
padding-right: 10px;
display: flex;
justify-content: center;
align-items: center;
`;

interface Props {
title: string;
}

export const MatchBottomBar: FC<Props> = ({ title }) => {
return (
<Container>
<Top>
<LeftContent>LOGO</LeftContent>
<CenterContent>{title}</CenterContent>
<RightContent></RightContent>
</Top>
</Container>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import styled from '@emotion/styled';
import { FC } from 'react';

const Container = styled.div`
transition: all 0.5s ease;
// top: -6.5vh;
position: relative;
z-index: 1;
`;

const Top = styled.div`
width: 100vw;
overflow: hidden;
height: 100%;
background-color: #101820;
color: #ffffff;
font-weight: bold;
font-size: 1.75vw;
display: flex;
justify-content: center;
align-items: center;
`;

const LeftContent = styled.div`
width: 10vw;
height: 100%;
padding-left: 10px;
display: flex;
justify-content: center;
align-items: center;
`;

const CenterContent = styled.div`
width: 80vw;
height: 100%;
padding-left: 10px;
display: flex;
justify-content: center;
align-items: center;
`;

const RightContent = styled.div`
width: 10vw;
height: 100%;
padding-right: 10px;
display: flex;
justify-content: center;
align-items: center;
`;

interface Props {
title: string;
}

export const MatchInfoBar: FC<Props> = ({ title }) => {
return (
<Container>
<Top>
<LeftContent>Up Next</LeftContent>
<CenterContent>{title}</CenterContent>
<RightContent>LOGO</RightContent>
</Top>
</Container>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import styled from '@emotion/styled';
import { FC } from 'react';
import { MatchInfoBar } from './components/match-info-bar';
import { MatchBottomBar } from './components/match-bottom-bar';
import { MatchAlliancePreview } from './components/match-alliance-preview';
import { Event, Match } from '@toa-lib/models';

const Container = styled.div`
display: grid;
grid-template-rows: 1fr 10fr 1fr;
grid-template-columns: 1fr;
grid-template-areas:
'header'
'content'
'footer';
height: 100vh;
overflow: hidden;
`;

const Content = styled.div`
height: 100%;
grid-area: content;
display: flex;
flex-direction: row;
width: 100%;
`;

interface Props {
match: Match<any>;
event: Event;
}

export const MatchPreview: FC<Props> = ({ event, match }) => {
return (
<Container>
<MatchInfoBar title={match.name} />
<Content>
<MatchAlliancePreview
alliance='red'
participants={match.participants ?? []}
/>
<MatchAlliancePreview
alliance='blue'
participants={match.participants ?? []}
/>
</Content>
<MatchBottomBar title={event.eventName} />
</Container>
);
};

0 comments on commit 9ead9f3

Please sign in to comment.