Skip to content

Commit

Permalink
add thingy for damon
Browse files Browse the repository at this point in the history
  • Loading branch information
alexanderjoe committed Jan 20, 2024
1 parent 1135e8b commit 77c0f8f
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 126 deletions.
8 changes: 4 additions & 4 deletions ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"type": "module",
"description": "Web UI for Accuribet",
"dependencies": {
"@kobalte/core": "^0.12.0",
"@kobalte/core": "^0.12.1",
"@solidjs/router": "^0.10.9",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
Expand Down
188 changes: 81 additions & 107 deletions ui/src/components/display-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,21 @@ import { Component, For, Show } from 'solid-js';
import { Game, Period, Team } from '~/interface';

import { FiCalendar, FiClock } from 'solid-icons/fi';
import { IoLocationOutline } from 'solid-icons/io';
import { IoLocationOutline } from 'solid-icons/io';
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 { formattedDateForUser } from '~/lib/utils';

const logos = import.meta.glob('../assets/teams/*.svg', { eager: true });

const getLogo = (team: string) => {
return logos[`../assets/teams/${team}.svg`].default;
};



const formattedTimeForUser = (time: number): string => {
/**
* Takes in a unix seconds timestamp and returns a formatted time string
Expand All @@ -35,13 +34,12 @@ const formattedTimeForUser = (time: number): string => {
};

const isLive = (game: Game): boolean => {
let time = game.start_time_unix
let time = game.start_time_unix;
let date = new Date(time * 1000);
let currentDate = new Date();
return date < currentDate
return date < currentDate;
};


const timeUntilGame = (game: Game): string => {
/**
* Takes in a unix seconds timestamp and returns a formatted time string
Expand All @@ -54,20 +52,6 @@ const timeUntilGame = (game: Game): string => {
const hours = Math.floor(diff / (1000 * 60 * 60));
const minutes = Math.floor((diff / (1000 * 60)) % 60);
return `${hours} hours, ${minutes} minutes`;
}

const formattedDateForUser = (time: number): string => {
/**
* Takes in a unix seconds timestamp and returns a formatted date string
* Like so: January 15, 2024
*/
const date = new Date(time * 1000); // Convert seconds to milliseconds
const options: Intl.DateTimeFormatOptions = {
year: 'numeric',
month: 'long',
day: 'numeric',
};
return new Intl.DateTimeFormat('en-US', options).format(date);
};

const winningTeam = (game: Game): number => {
Expand All @@ -82,7 +66,7 @@ interface IDisplayCard {
}

interface ITeamProps {
team: Team
team: Team;
}

export const ScoreTable: Component<ITeamProps> = (props: ITeamProps) => {
Expand All @@ -96,26 +80,14 @@ export const ScoreTable: Component<ITeamProps> = (props: ITeamProps) => {

return (
<Table class="mt-2">
<TableHeader>
<TableHeader class="bg-shark-700 text-shark-300">
<TableRow>
<For each={props.team.score.periods}>
{(period, _) => (
<TableHead class="text-center">
{formatPeriodType(period)}
</TableHead>
)}
</For>
<For each={props.team.score.periods}>{(period, _) => <TableHead class="text-center text-shark-300">{formatPeriodType(period)}</TableHead>}</For>
</TableRow>
</TableHeader>
<TableBody>
<TableBody class="bg-shark-600">
<TableRow>
<For each={props.team.score.periods}>
{(period, _) => (
<TableCell class="text-center">
{period.score}
</TableCell>
)}
</For>
<For each={props.team.score.periods}>{(period, _) => <TableCell class="text-center">{period.score}</TableCell>}</For>
</TableRow>
</TableBody>
</Table>
Expand All @@ -137,39 +109,42 @@ export const KeyPlayer: Component<ITeamProps> = (props: ITeamProps) => {
export const DemoCard: Component<IDisplayCard> = (props: IDisplayCard) => {
return (
<>
<Card class="w-full max-w-4xl mx-auto bg-gray-900 rounded-lg shadow-md overflow-hidden p-6 text-white border-4 border-gray-500">
<Card class="w-full max-w-4xl mx-auto bg-shark-900 rounded-lg shadow-md overflow-hidden p-6 text-white border-4 border-shark-600">
<CardHeader>
<div class="flex items-center justify-between">
<div class="flex items-center space-x-4">
<Avatar>
<AvatarImage alt="Detroit Pistons Logo" src={getLogo(props.game.home_team.abbreviation.toLowerCase())} />
</Avatar>
<div>
<CardTitle class="text-lg font-bold">{`${props.game.home_team.city} ${props.game.home_team.name}`}</CardTitle>
<CardDescription class="text-sm">{`${props.game.home_team.wins} - ${props.game.home_team.losses}`}</CardDescription>
<div class="flex flex-row items-center justify-between">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-4">
<Avatar>
<AvatarImage alt="Detroit Pistons Logo" src={getLogo(props.game.home_team.abbreviation.toLowerCase())} />
</Avatar>
<div>
<CardTitle class="text-lg font-bold">{`${props.game.home_team.city} ${props.game.home_team.name}`}</CardTitle>
<CardDescription class="text-sm">{`${props.game.home_team.wins} - ${props.game.home_team.losses}`}</CardDescription>
</div>
</div>
<Show when={winningTeam(props.game) === props.game.home_team.id}>
<Badge class="bg-yellow-500 text-black" variant="secondary">
Winner
</Badge>
</Show>
</div>
<Show when={winningTeam(props.game) === props.game.home_team.id}>
<Badge class="bg-yellow-500 text-black" variant="secondary">
Winner
</Badge>
</Show>
</div>
<div class="flex items-center justify-between mt-4">
<div class="flex items-center space-x-4">
<Avatar>
<AvatarImage alt="Minnesota Timberwolves Logo" src={getLogo(props.game.away_team.abbreviation.toLowerCase())} />
</Avatar>
<div>
<CardTitle class="text-lg font-bold">{`${props.game.away_team.city} ${props.game.away_team.name}`}</CardTitle>
<CardDescription class="text-sm">{`${props.game.away_team.wins} - ${props.game.away_team.losses}`}</CardDescription>
<span class="uppercase leading-3 font-bold text-sm text-gray-400">vs</span>
<div class="flex items-center justify-between mt-4">
<div class="flex items-center space-x-4">
<Avatar>
<AvatarImage alt="Minnesota Timberwolves Logo" src={getLogo(props.game.away_team.abbreviation.toLowerCase())} />
</Avatar>
<div>
<CardTitle class="text-lg font-bold">{`${props.game.away_team.city} ${props.game.away_team.name}`}</CardTitle>
<CardDescription class="text-sm">{`${props.game.away_team.wins} - ${props.game.away_team.losses}`}</CardDescription>
</div>
</div>
<Show when={winningTeam(props.game) === props.game.away_team.id}>
<Badge class="bg-yellow-500 text-black" variant="secondary">
Winner
</Badge>
</Show>
</div>
<Show when={winningTeam(props.game) === props.game.away_team.id}>
<Badge class="bg-yellow-500 text-black" variant="secondary">
Winner
</Badge>
</Show>
</div>
</CardHeader>
<CardContent class="">
Expand All @@ -185,15 +160,15 @@ export const DemoCard: Component<IDisplayCard> = (props: IDisplayCard) => {
</div>
</Show>
<Show when={!isLive(props.game)}>
<div class="flex items-center justify-center text-sm">
<FiClock class="mr-1 h-4 w-4 inline-block" />
<span class="ml-2">
{formattedTimeForUser(props.game.start_time_unix)}
<Show when={!isLive(props.game)}>
<p class="text-xs text-gray-400">{timeUntilGame(props.game)}</p>
</Show>
</span>
</div>
<div class="flex items-center justify-center text-sm">
<FiClock class="mr-1 h-4 w-4 inline-block" />
<span class="ml-2">
{formattedTimeForUser(props.game.start_time_unix)}
<Show when={!isLive(props.game)}>
<p class="text-xs text-gray-400">{timeUntilGame(props.game)}</p>
</Show>
</span>
</div>
</Show>
</div>
<div class="grid grid-cols-2 gap-4">
Expand All @@ -205,42 +180,42 @@ export const DemoCard: Component<IDisplayCard> = (props: IDisplayCard) => {
)}
</For>
<Show when={isLive(props.game)}>
<div class="col-span-2" id={`${props.game.id}-live-score`}>
<div class="text-center bg-gray-700 p-4 rounded-lg">
<div class="flex items-center justify-center mb-2">
<span class="text-red-500 animate-pulse mr-2">
<OcDotfill3 />
</span>
<span class="text-white font-bold">Live</span>
<div class="col-span-2" id={`${props.game.id}-live-score`}>
<div class="text-center bg-shark-800 p-4 rounded-lg">
<div class="flex items-center justify-center mb-2">
<span class="text-red-500 animate-pulse mr-2">
<OcDotfill3 />
</span>
<span class="text-white font-bold">Live</span>
</div>
<p class="text-2xl text-white font-bold mb-2">
{`${props.game.home_team.name}: ${props.game.home_team.score.points}`}
<span class={'text-sm text-gray-400 mx-3'}> - </span>
{`${props.game.away_team.name}: ${props.game.away_team.score.points}`}
</p>
<p class="text-sm text-gray-400">{props.game.status.includes('ET') ? 'Starting soon!' : props.game.status}</p>
</div>
<p class="text-2xl text-white font-bold mb-2">
{`${props.game.home_team.name}: ${props.game.home_team.score.points}`}
<span class={"text-sm text-gray-400 mx-3"}> - </span>
{`${props.game.away_team.name}: ${props.game.away_team.score.points}`}
</p>
<p class="text-sm text-gray-400">{props.game.status.includes('ET') ? 'Starting soon!' : props.game.status}</p>
</div>
</div>
<div>
<div class="mt-4">
<h3 class="text-lg font-bold">Score Breakdown - {props.game.home_team.name}</h3>
<ScoreTable team={props.game.home_team} />
</div>
<div class="mt-4">
<h4>Timeouts Remaining</h4>
<p>{props.game.home_team.name}: 2</p>
</div>
</div>
<div>
<div class="mt-4">
<h3 class="text-lg font-bold">Score Breakdown - {props.game.away_team.name}</h3>
<ScoreTable team={props.game.away_team} />
<div>
<div class="mt-4">
<h3 class="text-lg font-bold">Score Breakdown - {props.game.home_team.name}</h3>
<ScoreTable team={props.game.home_team} />
</div>
<div class="mt-4">
<h4>Timeouts Remaining</h4>
<p>{props.game.home_team.name}: 2</p>
</div>
</div>
<div class="mt-4">
<h4>Timeouts Remaining</h4>
<p>{props.game.away_team.name}: 1</p>
<div>
<div class="mt-4">
<h3 class="text-lg font-bold">Score Breakdown - {props.game.away_team.name}</h3>
<ScoreTable team={props.game.away_team} />
</div>
<div class="mt-4">
<h4>Timeouts Remaining</h4>
<p>{props.game.away_team.name}: 1</p>
</div>
</div>
</div>
</Show>
</div>
</CardContent>
Expand All @@ -253,4 +228,3 @@ export const DemoCard: Component<IDisplayCard> = (props: IDisplayCard) => {
</>
);
};

2 changes: 1 addition & 1 deletion ui/src/components/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Component } from 'solid-js';

export const Navbar: Component = () => {
return (
<header class="flex items-center justify-between px-6 py-4 bg-gray-900 text-white">
<header class="flex items-center justify-between px-6 py-4 bg-shark-950 text-white">
<h1 class="text-2xl font-bold">Accuribet</h1>
<nav class="space-x-4">
<Link class="hover:underline" href="/">
Expand Down
35 changes: 35 additions & 0 deletions ui/src/components/ui/switch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Component } from 'solid-js';
import { Show, splitProps } from 'solid-js';

import { Switch as SwitchPrimitive } from '@kobalte/core';

import { cn } from '~/lib/utils';

interface SwitchProps extends SwitchPrimitive.SwitchRootProps {
label?: string;
errorMessage?: string;
}

const Switch: Component<SwitchProps> = (props) => {
const [, rest] = splitProps(props, ['label']);
return (
<SwitchPrimitive.Root {...rest}>
<SwitchPrimitive.Input />
<div class="items-top flex space-x-2">
<SwitchPrimitive.Control class="bg-shark-500 focus-visible:ring-ring focus-visible:ring-offset-background data-[checked]:bg-shark-800 peer inline-flex h-[24px] w-[44px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50">
<SwitchPrimitive.Thumb class={cn('bg-background pointer-events-none block h-5 w-5 translate-x-0 rounded-full shadow-lg ring-0 transition-transform data-[checked]:translate-x-5')} />
</SwitchPrimitive.Control>
<div class="grid gap-1.5 leading-none">
<Show when={props.label}>
<SwitchPrimitive.Label class="text-sm font-medium leading-none group-data-[disabled]:cursor-not-allowed group-data-[disabled]:opacity-70">{props.label}</SwitchPrimitive.Label>
</Show>
<Show when={props.errorMessage}>
<SwitchPrimitive.ErrorMessage class="text-destructive text-sm">{props.errorMessage}</SwitchPrimitive.ErrorMessage>
</Show>
</div>
</div>
</SwitchPrimitive.Root>
);
};

export { Switch };
14 changes: 14 additions & 0 deletions ui/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,17 @@ import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}

export const formattedDateForUser = (time: number): string => {
/**
* Takes in a unix seconds timestamp and returns a formatted date string
* Like so: January 15, 2024
*/
const date = new Date(time * 1000); // Convert seconds to milliseconds
const options: Intl.DateTimeFormatOptions = {
year: 'numeric',
month: 'long',
day: 'numeric',
};
return new Intl.DateTimeFormat('en-US', options).format(date);
};
Loading

0 comments on commit 77c0f8f

Please sign in to comment.