From a0548f095c108cb84d7c236b4294968fa1d965d5 Mon Sep 17 00:00:00 2001 From: Alexander Date: Sat, 20 Jan 2024 17:01:11 -0500 Subject: [PATCH] move animation outside of card --- ui/.prettierrc | 1 - ui/src/components/display-card.tsx | 325 ++++++++++++++++++----------- ui/src/pages/Games.tsx | 233 +++++++++++++-------- 3 files changed, 342 insertions(+), 217 deletions(-) diff --git a/ui/.prettierrc b/ui/.prettierrc index fd294d0..cc92d92 100644 --- a/ui/.prettierrc +++ b/ui/.prettierrc @@ -2,7 +2,6 @@ "semi": true, "tabWidth": 2, "useTabs": false, - "printWidth": 600, "singleQuote": true, "trailingComma": "all" } \ No newline at end of file diff --git a/ui/src/components/display-card.tsx b/ui/src/components/display-card.tsx index cdd9683..94268bd 100644 --- a/ui/src/components/display-card.tsx +++ b/ui/src/components/display-card.tsx @@ -7,8 +7,22 @@ import { OcDotfill3 } from 'solid-icons/oc'; import { Avatar, AvatarImage } from '~/components/ui/avatar'; import { Badge } from '~/components/ui/badge'; import { Button } from '~/components/ui/button'; -import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '~/components/ui/card'; -import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '~/components/ui/table'; +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from '~/components/ui/card'; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from '~/components/ui/table'; import { Prediction } from '~/model/prediction.ts'; import { AlertDialog, @@ -17,7 +31,6 @@ import { AlertDialogTitle, } from '~/components/ui/alert-dialog.tsx'; import { isLive, timeUntilGame } from '~/lib/utils.ts'; -import { Motion } from 'solid-motionone'; const logos = import.meta.glob('../assets/teams/*.svg', { eager: true }); @@ -43,7 +56,6 @@ const formattedTimeForUser = (time: number): string => { return new Intl.DateTimeFormat('en-US', options).format(date); }; - const getColorFromStatusAndOutcome = ( status: string, winner: boolean, @@ -59,10 +71,11 @@ const getColorFromStatusAndOutcome = ( } }; - const winningTeam = (game: GameWithPrediction): number => { if (game.status === 'Final') { - return game.home_team.score.points > game.away_team.score.points ? game.home_team.id : game.away_team.id; + return game.home_team.score.points > game.away_team.score.points + ? game.home_team.id + : game.away_team.id; } return 0; }; @@ -95,15 +108,26 @@ export const ScoreTable: Component = (props: ITeamProps) => { - {(period, _) => {formatPeriodType(period)}} + + {(period, _) => ( + + {formatPeriodType(period)} + + )} + - {(period, _) => {period.score === null || period.score === 0 ? '-' : period.score - }} + + {(period, _) => ( + + {period.score === null || period.score === 0 + ? '-' + : period.score} + + )} +
@@ -116,7 +140,9 @@ export const KeyPlayer: Component = (props: ITeamProps) => {

Key Player - {props.team.name}

{props.team.leader.name}

Points: {props.team.leader.points}

-

Rebounds: {props.team.leader.rebounds}

+

+ Rebounds: {props.team.leader.rebounds} +

Assists: {props.team.leader.assists}

); @@ -139,11 +165,21 @@ export const TeamInfo: Component = (props: ITeamInfoProps) => { Winner - Projected Winner + when={ + props.prediction && + props.prediction.prediction_type === 'win-loss' && + props.prediction.prediction === + `${props.team.city} ${props.team.name}` + } + > + + Projected Winner + @@ -166,134 +202,173 @@ export const DemoCard: Component = (props: IDisplayCard) => { const [injuryReportOpen, setInjuryReportOpen] = createSignal(false); return ( <> - - - -
- - vs - -
-
- -
- -
- - {`${props.game.location.name}, ${props.game.location.city}, ${props.game.location.state}`} -
-
- -
- - + + +
+ + + vs + + +
+
+ +
+ +
+ + {`${props.game.location.name}, ${props.game.location.city}, ${props.game.location.state}`} +
+
+ +
+ +

Postponed

- + {formattedTimeForUser(props.game.start_time_unix)} - +

{timeUntilGame(props.game)}

-
-
-
-
- - {(team, _) => ( - - - - )} - - -
-
-
- +
+ +
+
+ + {(team, _) => ( + + + + )} + + +
+
+
+ - Live - + Live + +
+
+
+

{props.game.home_team.name}

+

+ {props.game.home_team.score.points} +

-
-
-

{props.game.home_team.name}

-

{props.game.home_team.score.points}

-
- - -
-

{props.game.away_team.name}

-

{props.game.away_team.score.points}

-
+ - +
+

{props.game.away_team.name}

+

+ {props.game.away_team.score.points} +

-

{props.game.status.includes('ET') ? 'Starting soon!' : props.game.status}

+

+ {props.game.status.includes('ET') + ? 'Starting soon!' + : props.game.status} +

- - {(team, _) => ( - - )} - - -
- - - team.injuries.length > 0)}> - +
+ + {(team, _) => } +
- - - +
+ + + team.injuries.length > 0, + )} + > + + + + ); }; diff --git a/ui/src/pages/Games.tsx b/ui/src/pages/Games.tsx index 4d04ff0..adc624f 100644 --- a/ui/src/pages/Games.tsx +++ b/ui/src/pages/Games.tsx @@ -4,10 +4,25 @@ import { DemoCard as GameCard } from '~/components/display-card'; import { Loading } from '~/components/loading'; import { Switch } from '~/components/ui/switch'; import { Game, GameWithPrediction } from '~/interface'; -import { formattedDateForUser, isGameActuallyLive, isPredictionCorrect } from '~/lib/utils'; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '~/components/ui/select.tsx'; +import { + formattedDateForUser, + isGameActuallyLive, + isPredictionCorrect, +} from '~/lib/utils'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '~/components/ui/select.tsx'; import { Prediction } from '~/model/prediction.ts'; -import { Tooltip, TooltipContent, TooltipTrigger } from '~/components/ui/tooltip.tsx'; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from '~/components/ui/tooltip.tsx'; +import { Motion } from 'solid-motionone'; export const Games = () => { const [games, setGames] = createSignal([]); @@ -19,7 +34,9 @@ export const Games = () => { let intervalId: NodeJS.Timeout; const fetchGames = async () => { - const res = await fetch('https://apidev.accuribet.win/api/v1/games/daily?with_odds=true'); + const res = await fetch( + 'https://apidev.accuribet.win/api/v1/games/daily?with_odds=true', + ); const data = await res.json(); setGames(data as Game[]); @@ -33,8 +50,10 @@ export const Games = () => { }; const fetchPredictions = async (model: string) => { - if (!model) return - const cacheKey = `${games().map((game) => game.id).join('-')}--${model}`; + if (!model) return; + const cacheKey = `${games() + .map((game) => game.id) + .join('-')}--${model}`; const cachedPredictions = localStorage.getItem(cacheKey); if (cachedPredictions) { console.log('Using cached predictions'); @@ -43,19 +62,20 @@ export const Games = () => { return; } - - const res = await fetch(`https://apidev.accuribet.win/api/v1/model/predict/${model}`); - const data = await res.json() as Prediction[]; + const res = await fetch( + `https://apidev.accuribet.win/api/v1/model/predict/${model}`, + ); + const data = (await res.json()) as Prediction[]; localStorage.setItem(cacheKey, JSON.stringify(data)); setPredictions(data); setSelectedModel(model); - } + }; const toggleLiveUpdates = () => { setLiveUpdates(!liveUpdates()); if (liveUpdates()) { - intervalId = setInterval(fetchGames, 30_000); + intervalId = setInterval(fetchGames, 3_000); } else { clearInterval(intervalId); } @@ -64,45 +84,50 @@ export const Games = () => { const gamesPlaying = (games: Game[]): boolean => { return games .filter((game) => game.status.toLowerCase() !== 'ppd') - .some((game) => game.status.toLowerCase().includes('q') || game.status.toLowerCase().includes('h')); - } - - - - - - - const getGamesWithPredictions = (games: Game[], prediction: Prediction[]): GameWithPrediction[] => { - return games.map((game) => { - const gamePrediction = prediction.find((pred) => pred.game_id === game.id); - return { - ...game, - prediction: gamePrediction, - }; - }).sort((a, b) => { - // Live games come first - if (isGameActuallyLive(a) && !isGameActuallyLive(b)) return -1; - if (!isGameActuallyLive(a) && isGameActuallyLive(b)) return 1; - - // Then games with status 'Final' - if (a.status === 'Final' && b.status !== 'Final') return -1; - if (a.status !== 'Final' && b.status === 'Final') return 1; - - // Among 'Final' games, correctly predicted games come first - if (a.status === 'Final' && b.status === 'Final') { - if (isPredictionCorrect(a) && !isPredictionCorrect(b)) return -1; - if (!isPredictionCorrect(a) && isPredictionCorrect(b)) return 1; - } - - // Postponed games come last - if (a.status === 'ppd' && b.status !== 'ppd') return 1; - if (a.status !== 'ppd' && b.status === 'ppd') return -1; - - // If none of the above conditions are met, don't change order - return 0; - }); - } + .some( + (game) => + game.status.toLowerCase().includes('q') || + game.status.toLowerCase().includes('h'), + ); + }; + const getGamesWithPredictions = ( + games: Game[], + prediction: Prediction[], + ): GameWithPrediction[] => { + return games + .map((game) => { + const gamePrediction = prediction.find( + (pred) => pred.game_id === game.id, + ); + return { + ...game, + prediction: gamePrediction, + }; + }) + .sort((a, b) => { + // Live games come first + if (isGameActuallyLive(a) && !isGameActuallyLive(b)) return -1; + if (!isGameActuallyLive(a) && isGameActuallyLive(b)) return 1; + + // Then games with status 'Final' + if (a.status === 'Final' && b.status !== 'Final') return -1; + if (a.status !== 'Final' && b.status === 'Final') return 1; + + // Among 'Final' games, correctly predicted games come first + if (a.status === 'Final' && b.status === 'Final') { + if (isPredictionCorrect(a) && !isPredictionCorrect(b)) return -1; + if (!isPredictionCorrect(a) && isPredictionCorrect(b)) return 1; + } + + // Postponed games come last + if (a.status === 'ppd' && b.status !== 'ppd') return 1; + if (a.status !== 'ppd' && b.status === 'ppd') return -1; + + // If none of the above conditions are met, don't change order + return 0; + }); + }; onMount(async () => { await fetchGames(); @@ -117,54 +142,80 @@ export const Games = () => { return (
0} keyed fallback={}> -
-
- -
-
-
- - {formattedDateForUser(games()[0].start_time_unix)} + +
+
+
+
+
+ + + {formattedDateForUser(games()[0].start_time_unix)} + +
-
- Live Updates - - - - +
+ Live Updates + + + + - - { - gamesPlaying(games()) ? - `Live updates will be gathered every 30 seconds` : - `Live updates are disabled until games start` - } + {gamesPlaying(games()) + ? `Live updates will be gathered every 30 seconds` + : `Live updates are disabled until games start`} - + +
-
- - {(game) => ( -
- -
- )} -
-
+ + {(game) => ( +
+ +
+ )} +
+
+
);