Skip to content

Commit

Permalink
goodnight
Browse files Browse the repository at this point in the history
  • Loading branch information
day-mon committed Jan 20, 2024
1 parent 0910403 commit bcc4a69
Show file tree
Hide file tree
Showing 9 changed files with 397 additions and 23 deletions.
52 changes: 36 additions & 16 deletions ui/src/components/display-card.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, For, Show } from 'solid-js';
import { Game, Period, Team } from '~/interface';
import { Game, GameWithPrediction, Period, Team } from '~/interface';

import { FiClock } from 'solid-icons/fi';
import { IoLocationOutline } from 'solid-icons/io';
Expand All @@ -9,11 +9,13 @@ 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 { Prediction } from '~/model/prediction.ts';

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

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

Expand Down Expand Up @@ -42,11 +44,23 @@ const isLive = (game: Game): boolean => {
}
let status = game.status.toLowerCase();
return status !== 'ppd';


};

const timeUntilGame = (game: Game): string => {
const getColorFromStatusAndOutcome = (
status: string,
winner: boolean,
): string => {
if (status === 'Final') {
if (winner) {
return 'bg-emerald-600';
} else {
return 'bg-red-600';
}
} else {
return 'bg-yellow-600';
}
}
const timeUntilGame = (game: GameWithPrediction): string => {
/**
* Takes in a unix seconds timestamp and returns a formatted time string
* for the user.
Expand All @@ -60,15 +74,15 @@ const timeUntilGame = (game: Game): string => {
return `${hours} hours, ${minutes} minutes`;
};

const winningTeam = (game: Game): number => {
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 0;
};

interface IDisplayCard {
game: Game;
game: GameWithPrediction;
}

interface ITeamProps {
Expand All @@ -78,6 +92,8 @@ interface ITeamProps {
interface ITeamInfoProps {
team: Team;
winner: number;
prediction?: Prediction
game: GameWithPrediction;
}

export const ScoreTable: Component<ITeamProps> = (props: ITeamProps) => {
Expand Down Expand Up @@ -130,8 +146,11 @@ export const TeamInfo: Component<ITeamInfoProps> = (props: ITeamInfoProps) => {
<Show when={props.winner === props.team.id}>
<Badge class="bg-yellow-600 text-black">Winner</Badge>
</Show>
<Show when={props.winner !== props.team.id}>
<Badge class="ml-2 bg-emerald-900 text-gray-200">Projected Winner</Badge>
<Show when={props.prediction && props.prediction.prediction_type === "win-loss" && props.prediction.prediction === `${props.team.city} ${props.team.name}`}>
<Badge class={`ml-2 ${getColorFromStatusAndOutcome(
props.game.status,
props.winner === props.team.id
)} text-white`}>Projected Winner</Badge>
</Show>
</span>
</CardDescription>
Expand All @@ -146,10 +165,6 @@ export const AdvancedGameCard: Component<ITeamProps> = (props: ITeamProps) => {
<h3 class='text-lg font-bold'>Score Breakdown - {props.team.name}</h3>
<ScoreTable team={props.team} />
</div>
<div class='mt-4'>
<h4>Timeouts Remaining</h4>
<p>{props.team.name}: 2</p>
</div>
</div>
)
}
Expand All @@ -161,9 +176,9 @@ export const DemoCard: Component<IDisplayCard> = (props: IDisplayCard) => {
class='w-full max-w-4xl mx-auto bg-shark-900 rounded-lg shadow-md overflow-hidden p-4 text-white border-4 border-white'>
<CardHeader>
<div class='flex flex-row items-center justify-between'>
<TeamInfo team={props.game.home_team} winner={winningTeam(props.game)} />
<TeamInfo team={props.game.home_team} winner={winningTeam(props.game)} prediction={props.game.prediction} game={props.game} />
<span class="uppercase leading-3 font-boldtext-sm text-shark-400">vs</span>
<TeamInfo team={props.game.away_team} winner={winningTeam(props.game)} />
<TeamInfo team={props.game.away_team} winner={winningTeam(props.game)} prediction={props.game.prediction} game={props.game} />
</div>
</CardHeader>
<CardContent class="">
Expand All @@ -182,9 +197,14 @@ export const DemoCard: Component<IDisplayCard> = (props: IDisplayCard) => {
<p class="text-xs text-gray-400">Postponed</p>
</Show>

{formattedTimeForUser(props.game.start_time_unix)}
<span class={`${props.game.status === 'PPD' ? 'line-through': ''} `}>
{formattedTimeForUser(props.game.start_time_unix)}
</span>

<Show when={!isLive(props.game) && props.game.status !== 'PPD'}>
<p class={`text-xs text-gray-400 font-bold ${props.game.status === 'PPD' ? 'line-through': ''} `}>{timeUntilGame(props.game)}</p>
<p class={`text-xs text-gray-400 font-bold`}>
{timeUntilGame(props.game)}
</p>
</Show>
</span>
</div>
Expand Down
111 changes: 111 additions & 0 deletions ui/src/components/ui/combobox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import type { Component } from "solid-js"
import { splitProps } from "solid-js"

import { Combobox as ComboboxPrimitive } from "@kobalte/core"
import { TbCheck, TbSelector } from "solid-icons/tb"

import { cn } from "~/lib/utils"

const Combobox = ComboboxPrimitive.Root

const ComboboxItem: Component<ComboboxPrimitive.ComboboxItemProps> = (props) => {
const [, rest] = splitProps(props, ["class"])
return (
<ComboboxPrimitive.Item
class={cn(
"data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative flex cursor-default select-none items-center justify-between rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
props.class
)}
{...rest}
/>
)
}

const ComboboxItemLabel = ComboboxPrimitive.ItemLabel

const ComboboxItemIndicator: Component<ComboboxPrimitive.ComboboxItemIndicatorProps> = (props) => {
const [, rest] = splitProps(props, ["children"])
return (
<ComboboxPrimitive.ItemIndicator {...rest}>
{props.children ?? <TbCheck />}
</ComboboxPrimitive.ItemIndicator>
)
}

const ComboboxSection: Component<ComboboxPrimitive.ComboboxSectionProps> = (props) => {
const [, rest] = splitProps(props, ["class"])
return (
<ComboboxPrimitive.Section
class={cn(
"text-muted-foreground overflow-hidden p-1 px-2 py-1.5 text-xs font-medium ",
props.class
)}
{...rest}
/>
)
}

// due to the generic typing this needs to be a function
function ComboboxControl<T>(props: ComboboxPrimitive.ComboboxControlProps<T>) {
const [, rest] = splitProps(props, ["class"])
return (
<ComboboxPrimitive.Control
class={cn("flex items-center rounded-md border px-3", props.class)}
{...rest}
/>
)
}

const ComboboxInput: Component<ComboboxPrimitive.ComboboxInputProps> = (props) => {
const [, rest] = splitProps(props, ["class"])
return (
<ComboboxPrimitive.Input
class={cn(
"placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none disabled:cursor-not-allowed disabled:opacity-50",
props.class
)}
{...rest}
/>
)
}

const ComboboxHiddenSelect = ComboboxPrimitive.HiddenSelect

const ComboboxTrigger: Component<ComboboxPrimitive.ComboboxTriggerProps> = (props) => {
const [, rest] = splitProps(props, ["class", "children"])
return (
<ComboboxPrimitive.Trigger class={cn("h-4 w-4 opacity-50", props.class)} {...rest}>
<ComboboxPrimitive.Icon>{props.children ?? <TbSelector />}</ComboboxPrimitive.Icon>
</ComboboxPrimitive.Trigger>
)
}

const ComboboxContent: Component<ComboboxPrimitive.ComboboxContentProps> = (props) => {
const [, rest] = splitProps(props, ["class"])
return (
<ComboboxPrimitive.Portal>
<ComboboxPrimitive.Content
class={cn(
"bg-popover text-popover-foreground animate-in fade-in-80 relative z-50 min-w-[8rem] overflow-hidden rounded-md border shadow-md",
props.class
)}
{...rest}
>
<ComboboxPrimitive.Listbox class="m-0 p-1" />
</ComboboxPrimitive.Content>
</ComboboxPrimitive.Portal>
)
}

export {
Combobox,
ComboboxItem,
ComboboxItemLabel,
ComboboxItemIndicator,
ComboboxSection,
ComboboxControl,
ComboboxTrigger,
ComboboxInput,
ComboboxHiddenSelect,
ComboboxContent
}
29 changes: 29 additions & 0 deletions ui/src/components/ui/hover-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { Component } from "solid-js"
import { splitProps } from "solid-js"

import { HoverCard as HoverCardPrimitive } from "@kobalte/core"

import { cn } from "~/lib/utils"

const HoverCard: Component<HoverCardPrimitive.HoverCardRootProps> = (props) => {
return <HoverCardPrimitive.Root gutter={4} {...props} />
}

const HoverCardTrigger = HoverCardPrimitive.Trigger

const HoverCardContent: Component<HoverCardPrimitive.HoverCardContentProps> = (props) => {
const [, rest] = splitProps(props, ["class"])
return (
<HoverCardPrimitive.Portal>
<HoverCardPrimitive.Content
class={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64 rounded-md border p-4 shadow-md outline-none",
props.class
)}
{...rest}
/>
</HoverCardPrimitive.Portal>
)
}

export { HoverCard, HoverCardTrigger, HoverCardContent }
68 changes: 68 additions & 0 deletions ui/src/components/ui/select.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import type { Component } from "solid-js"
import { splitProps } from "solid-js"

import { Select as SelectPrimitive } from "@kobalte/core"
import { TbCheck, TbChevronDown } from "solid-icons/tb"

import { cn } from "~/lib/utils"

const Select = SelectPrimitive.Root

const SelectValue = SelectPrimitive.Value

const SelectTrigger: Component<SelectPrimitive.SelectTriggerProps> = (props) => {
const [, rest] = splitProps(props, ["class", "children"])
return (
<SelectPrimitive.Trigger
class={cn(
"border-input ring-offset-background placeholder:text-muted-foreground focus:ring-ring flex h-10 w-full items-center justify-between rounded-md border bg-transparent px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
props.class
)}
{...rest}
>
{props.children}
<SelectPrimitive.Icon>
<TbChevronDown class="h-4 w-4 opacity-50" />
</SelectPrimitive.Icon>
</SelectPrimitive.Trigger>
)
}

const SelectContent: Component<SelectPrimitive.SelectContentProps> = (props) => {
const [, rest] = splitProps(props, ["class"])
return (
<SelectPrimitive.Portal>
<SelectPrimitive.Content
class={cn(
"bg-popover text-popover-foreground animate-in fade-in-80 relative z-50 min-w-[8rem] overflow-hidden rounded-md border shadow-md",
props.class
)}
{...rest}
>
<SelectPrimitive.Listbox class="m-0 p-1" />
</SelectPrimitive.Content>
</SelectPrimitive.Portal>
)
}

const SelectItem: Component<SelectPrimitive.SelectItemProps> = (props) => {
const [, rest] = splitProps(props, ["class", "children"])
return (
<SelectPrimitive.Item
class={cn(
"focus:bg-accent focus:text-accent-foreground relative mt-0 flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
props.class
)}
{...rest}
>
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<SelectPrimitive.ItemIndicator>
<TbCheck class="h-4 w-4" />
</SelectPrimitive.ItemIndicator>
</span>
<SelectPrimitive.ItemLabel>{props.children}</SelectPrimitive.ItemLabel>
</SelectPrimitive.Item>
)
}

export { Select, SelectValue, SelectTrigger, SelectContent, SelectItem }
2 changes: 2 additions & 0 deletions ui/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
@tailwind components;
@tailwind utilities;



@layer base {
:root {
--background: 0 0% 100%;
Expand Down
6 changes: 6 additions & 0 deletions ui/src/interface.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Prediction } from '~/model/prediction.ts';

export interface Game {
id: string;
date: string;
Expand All @@ -9,6 +11,10 @@ export interface Game {
odds: Odds[];
}

export interface GameWithPrediction extends Game {
prediction?: Prediction;
}

export interface Location {
name: string;
city: string;
Expand Down
Loading

0 comments on commit bcc4a69

Please sign in to comment.