Skip to content

Commit

Permalink
qualifiers screen + reorg
Browse files Browse the repository at this point in the history
  • Loading branch information
swantzter committed Jul 15, 2024
1 parent d73f073 commit 2cb4102
Show file tree
Hide file tree
Showing 19 changed files with 368 additions and 79 deletions.
6 changes: 5 additions & 1 deletion src/hooks/heat-info.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { type Ref, ref, watch } from 'vue'
import { useFetch, useTimeoutPoll } from '@vueuse/core'
import type { ServoCurrentHeatInfoConfig } from './stream-pools'
export interface ServoCurrentHeatInfoConfig {
system: 'servo'
baseUrl: string
competitionId?: number
}

export interface ServoHeatInfo {
PROGRAM: 'ON' | ''
Expand Down
23 changes: 13 additions & 10 deletions src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,22 @@ const router = createRouter({
{ path: '/auth', component: async () => import('./views/Auth.vue') },

{ path: '/groups', component: async () => import('./views/Groups.vue'), meta: { authRequired: true, menu: 'Groups', menuOrder: 2 } },
{ path: '/groups/:groupId/live', component: async () => import('./views/Live.vue'), meta: { fullscreen: true, authRequired: true } },
{ path: '/groups/:groupId/on-floor', component: async () => import('./views/OnFloor.vue'), meta: { fullscreen: true, authRequired: true } },
{ path: '/groups/:groupId/next-up', component: async () => import('./views/NextUp.vue'), meta: { fullscreen: true, authRequired: true } },
{ path: '/groups/:groupId/leaderboard', component: async () => import('./views/Leaderboard.vue'), meta: { fullscreen: true, authRequired: true } },
{ path: '/groups/:groupId/live', component: async () => import('./views/ropescore/Live.vue'), meta: { fullscreen: true, authRequired: true } },
{ path: '/groups/:groupId/on-floor', component: async () => import('./views/ropescore/OnFloor.vue'), meta: { fullscreen: true, authRequired: true } },
{ path: '/groups/:groupId/next-up', component: async () => import('./views/ropescore/NextUp.vue'), meta: { fullscreen: true, authRequired: true } },
{ path: '/groups/:groupId/leaderboard', component: async () => import('./views/ropescore/Leaderboard.vue'), meta: { fullscreen: true, authRequired: true } },

{ path: '/device-stream', component: async () => import('./views/DeviceStreamConfig.vue'), meta: { authRequired: true, menu: 'Device Stream', menuOrder: 3 } },
{ path: '/device-stream/live', component: async () => import('./views/DeviceStreamLive.vue'), meta: { fullscreen: true, authRequired: true } },
{ path: '/device-stream', component: async () => import('./views/device-stream/Config.vue'), meta: { authRequired: true, menu: 'Device Stream', menuOrder: 3 } },
{ path: '/device-stream/display', component: async () => import('./views/device-stream/Display.vue'), meta: { fullscreen: true, authRequired: true } },

{ path: '/podium', component: async () => import('./views/PodiumConfig.vue'), meta: { menu: 'Podium', menuOrder: 4 } },
{ path: '/podium/live', component: async () => import('./views/PodiumLive.vue'), meta: { fullscreen: true } },
{ path: '/podium', component: async () => import('./views/podium/Config.vue'), meta: { menu: 'Podium', menuOrder: 4 } },
{ path: '/podium/display', component: async () => import('./views/podium/Display.vue'), meta: { fullscreen: true } },

{ path: '/on-floor-wall/', component: async () => import('./views/OnFloorWallConfig.vue'), meta: { menu: 'On Floor Wall', menuOrder: 5 } },
{ path: '/on-floor-wall/:vendor/:id', component: async () => import('./views/OnFloorWallLive.vue'), meta: { fullscreen: true } }
{ path: '/on-floor-wall/', component: async () => import('./views/on-floor-wall/Config.vue'), meta: { menu: 'On Floor Wall', menuOrder: 5 } },
{ path: '/on-floor-wall/display', component: async () => import('./views/on-floor-wall/Display.vue'), meta: { fullscreen: true } },

{ path: '/qualifiers/', component: async () => import('./views/qualifiers/Config.vue'), meta: { menu: 'Qualifiers', menuOrder: 6 } },
{ path: '/qualifiers/display', component: async () => import('./views/qualifiers/Display.vue'), meta: { fullscreen: true } }
]
})
export default router
Expand Down
2 changes: 1 addition & 1 deletion src/views/Groups.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</div>

<menu class="p-0 m-0 flex justify-end items-start flex-col">
<button-link :to="`/groups/${group.id}/live?theme=${theme}&key-color=${keyColor}`">
<button-link :to="`/groups/${group.id}/display?theme=${theme}&key-color=${keyColor}`">
Live
</button-link>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
Screen {{ screenId }}
</h3>
<div>
<button-link :to="`/device-stream/live?screen-id=${screenId}&theme=${theme}`" target="_blank">
<button-link :to="`/device-stream/display?screen-id=${screenId}&theme=${theme}`" target="_blank">
Show Scores
</button-link>
<text-button color="red" @click="removeScreen(screenId)">
Expand Down Expand Up @@ -199,15 +199,15 @@
<script lang="ts" setup>
import { ref, computed } from 'vue'
import { useDeviceStreamPools } from '../hooks/stream-pools'
import { DeviceStreamShareStatus, useRequestStreamShareMutation, useUserStreamSharesQuery } from '../graphql/generated'
import { useDeviceStreamPools } from './use-device-stream-pools'
import { DeviceStreamShareStatus, useRequestStreamShareMutation, useUserStreamSharesQuery } from '../../graphql/generated'
import { useHead } from '@vueuse/head'
import { TextButton, TextField, SelectField, ButtonLink, NumberField } from '@ropescore/components'
import IconLoading from 'virtual:icons/mdi/loading'
import IconPlus from 'virtual:icons/mdi/plus'
import useFirebaseAuth from '../hooks/firebase-auth'
import { useTheme } from '../hooks/theme'
import useFirebaseAuth from '../../hooks/firebase-auth'
import { useTheme } from '../../hooks/theme'
useHead({
title: 'Device Stream'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,18 @@
<script lang="ts" setup>
import { computed, reactive, ref, watch } from 'vue'
import { type DeviceStreamJudgeInfo, type DeviceStreamMarkAddedSubscription, useDeviceStreamMarkAddedSubscription } from '../graphql/generated'
import { type ScoreTally, type Mark, formatList } from '../helpers'
import { useDeviceStreamPools } from '../hooks/stream-pools'
import { type DeviceStreamJudgeInfo, type DeviceStreamMarkAddedSubscription, useDeviceStreamMarkAddedSubscription } from '../../graphql/generated'
import { type ScoreTally, type Mark, formatList } from '../../helpers'
import { useDeviceStreamPools } from './use-device-stream-pools'
import { useHead } from '@vueuse/head'
import { useRouteQuery } from '@vueuse/router'
import { useTheme } from '../hooks/theme'
import { useTheme } from '../../hooks/theme'
import DeviceNotSet from '../components/DeviceNotSet.vue'
import SpeedLiveScore from '../components/SpeedLiveScore.vue'
import TimingLiveScore from '../components/TimingLiveScore.vue'
import UnsupportedCompetitionEvent from '../components/UnsupportedCompetitionEvent.vue'
import { getHeatNameList, useHeatInfo } from '../hooks/heat-info'
import DeviceNotSet from '../../components/DeviceNotSet.vue'
import SpeedLiveScore from '../../components/SpeedLiveScore.vue'
import TimingLiveScore from '../../components/TimingLiveScore.vue'
import UnsupportedCompetitionEvent from '../../components/UnsupportedCompetitionEvent.vue'
import { getHeatNameList, useHeatInfo } from '../../hooks/heat-info'
import { useDateFormat, useTimestamp } from '@vueuse/core'
useHead({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
import { useLocalStorage } from '@vueuse/core'
import type { ServoCurrentHeatInfoConfig } from '../../hooks/heat-info'

export interface StreamPool {
deviceId?: string
label?: number
}

export interface ServoCurrentHeatInfoConfig {
system: 'servo'
baseUrl: string
competitionId?: number
}

export interface ScreenConfig {
rows: number
cols: number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="mb-4 mx-auto container flex justify-between">
<div />
<button-link
:to="`/on-floor-wall/${settings.heatInfo?.system}/${settings.heatInfo?.competitionId}?theme=${theme}`"
:to="`/on-floor-wall/display?theme=${theme}`"
:disabled="settings.heatInfo?.system == null || settings.heatInfo?.competitionId == null"
>
Display
Expand Down Expand Up @@ -47,12 +47,12 @@
</template>
<script lang="ts" setup>
import countries from '../assets/countries.json'
import countries from '../../assets/countries.json'
import { SelectField, NumberField, TextField, ButtonLink } from '@ropescore/components'
import { useHead } from '@vueuse/head'
import PhotoPicker from '../components/PhotoPicker.vue'
import { useTheme } from '../hooks/theme'
import { useOnFloorWallSettings } from '../hooks/on-floor-wall'
import PhotoPicker from '../../components/PhotoPicker.vue'
import { useTheme } from '../../hooks/theme'
import { useOnFloorWallSettings } from './use-on-floor-wall'
useHead({
title: 'On Floor Wall'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@
class="flex h-full items-center justify-end col-start-[var(--station-col,1)] row-start-[calc(var(--station-row,1)+1)] bg-white p-2"
>
<img
:style="`--station :${heat.Station}`"
class="border-2"
:class="{
'border-gray-800': theme !== 'dark',
Expand Down Expand Up @@ -116,10 +115,10 @@
<script lang="ts" setup>
import { computed, ref, watch } from 'vue'
import { useHead } from '@vueuse/head'
import { formatList, getOpfsImgUrl } from '../helpers'
import { useTheme } from '../hooks/theme'
import { useOnFloorWallSettings } from '../hooks/on-floor-wall'
import { getHeatNameList, useHeatInfo, type ServoHeatInfo } from '../hooks/heat-info'
import { formatList, getOpfsImgUrl } from '../../helpers'
import { useTheme } from '../../hooks/theme'
import { useOnFloorWallSettings } from './use-on-floor-wall'
import { getHeatNameList, useHeatInfo, type ServoHeatInfo } from '../../hooks/heat-info'
import { useDateFormat, useTimestamp } from '@vueuse/core'
useHead({
Expand All @@ -143,15 +142,7 @@ function flagUrl (hi: ServoHeatInfo) {
return hi.TeamCountryFlagUrl || (hi.TeamCountryCode ? `/flags/${hi.TeamCountryCode.toLocaleLowerCase()}.svg` : undefined)
}
// const heatInfos = heatInfo.data
const heatInfos = ref<ServoHeatInfo[] | null>([
{"PROGRAM":"ON","Station":1,"HeatNumber":"10","Event":"Single Rope Double Unders Relay","Team":"Denmark","TeamCountryCode":"DK","TeamCountryName":"Denmark","TeamCountryFlagUrl":"https://scoring.ijru.sport/Content/flags/svg/dk.svg","Part1":"Liva Bondesen","Part2":"Mathilde Vig Jeppesen","Part3":"","Part4":"","Part5":"","Part1_Last":"Bondesen","Part2_Last":"Vig Jeppesen","Part3_Last":"","Part4_Last":"","Part5_Last":"","DivisionName":"EOT","AgeGroupName":"12-15","GenderName":"Female","EntryNumber":76,"CompEventEntryID":"a0652070-037d-4227-99bb-fab54772bc18"},
{"PROGRAM":"","Station":2,"HeatNumber":"10","Event":"Single Rope Double Unders Relay","Team":"Denmark","TeamCountryCode":"DK","TeamCountryName":"Denmark","TeamCountryFlagUrl":"https://scoring.ijru.sport/Content/flags/svg/dk.svg","Part1":"Ida Stampe Bornø","Part2":"Kassandra Lu-Nielsen","Part3":"","Part4":"","Part5":"","Part1_Last":"Stampe Bornø","Part2_Last":"Lu-Nielsen","Part3_Last":"","Part4_Last":"","Part5_Last":"","DivisionName":"EOT","AgeGroupName":"12-15","GenderName":"Female","EntryNumber":77,"CompEventEntryID":"c3cfc6ee-46ea-4e29-8dca-1f5da1fb5089"},
{"PROGRAM":"","Station":3,"HeatNumber":"10","Event":"Single Rope Double Unders Relay","Team":"Belgium","TeamCountryCode":"BE","TeamCountryName":"Belgium","TeamCountryFlagUrl":"https://scoring.ijru.sport/Content/flags/svg/be.svg","Part1":"Klara De Baets","Part2":"Emma Vander Gheynst","Part3":"","Part4":"","Part5":"","Part1_Last":"De Baets","Part2_Last":"Vander Gheynst","Part3_Last":"","Part4_Last":"","Part5_Last":"","DivisionName":"EOT","AgeGroupName":"12-15","GenderName":"Female","EntryNumber":73,"CompEventEntryID":"54624b11-195f-4340-a7a9-2bfd65fc377c"},
{"PROGRAM":"","Station":4,"HeatNumber":"10","Event":"Single Rope Double Unders Relay","Team":"Sweden","TeamCountryCode":"SE","TeamCountryName":"Sweden","TeamCountryFlagUrl":"https://scoring.ijru.sport/Content/flags/svg/se.svg","Part1":"Alva Karlsson","Part2":"Majken Olsson","Part3":"","Part4":"","Part5":"","Part1_Last":"Karlsson","Part2_Last":"Olsson","Part3_Last":"","Part4_Last":"","Part5_Last":"","DivisionName":"EOT","AgeGroupName":"12-15","GenderName":"Female","EntryNumber":81,"CompEventEntryID":"946ac1dc-5cdc-4283-a254-3fb460622a70"},
{"PROGRAM":"","Station":5,"HeatNumber":"10","Event":"Single Rope Double Unders Relay","Team":"Germany","TeamCountryCode":"DE","TeamCountryName":"Germany","TeamCountryFlagUrl":"https://scoring.ijru.sport/Content/flags/svg/de.svg","Part1":"Theresa Pätzmann","Part2":"Frieda Rauscher","Part3":"","Part4":"","Part5":"","Part1_Last":"Pätzmann","Part2_Last":"Rauscher","Part3_Last":"","Part4_Last":"","Part5_Last":"","DivisionName":"EOT","AgeGroupName":"12-15","GenderName":"Female","EntryNumber":79,"CompEventEntryID":"5d81c54f-9489-4fa6-a858-5da1e3667663"},
{"PROGRAM":"","Station":6,"HeatNumber":"10","Event":"Single Rope Double Unders Relay","Team":"Sweden","TeamCountryCode":"SE","TeamCountryName":"Sweden","TeamCountryFlagUrl":"https://scoring.ijru.sport/Content/flags/svg/se.svg","Part1":"Isabella Danfelter","Part2":"Molly Löfberg","Part3":"","Part4":"","Part5":"","Part1_Last":"Danfelter","Part2_Last":"Löfberg","Part3_Last":"","Part4_Last":"","Part5_Last":"","DivisionName":"EOT","AgeGroupName":"12-15","GenderName":"Female","EntryNumber":82,"CompEventEntryID":"03b3a376-90d8-41ab-8515-20366848d056"},
])
const heatInfos = heatInfo.data
const grid = computed(() => {
const maxStation = Math.max(...((heatInfos.value ?? [] as ServoHeatInfo[]).map(hi => hi.Station)))
Expand Down Expand Up @@ -206,8 +197,4 @@ main.dark {
background-repeat: no-repeat;
background-size: cover;
}
.overflow-ellipsis {
text-overflow: ellipsis;
}
</style>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useLocalStorage } from '@vueuse/core'
import type { ServoCurrentHeatInfoConfig } from './stream-pools'
import type { ServoCurrentHeatInfoConfig } from '../../hooks/heat-info'

export interface OnFloorWallSettings {
heatInfo?: ServoCurrentHeatInfoConfig
Expand Down
10 changes: 5 additions & 5 deletions src/views/PodiumConfig.vue → src/views/podium/Config.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
Title
</text-button>
</div>
<button-link :to="`/podium/live?theme=${theme}`">
<button-link :to="`/podium/display?theme=${theme}`">
Display
</button-link>
</div>
Expand Down Expand Up @@ -79,12 +79,12 @@

<script lang="ts" setup>
import { nextTick, ref } from 'vue'
import countries from '../assets/countries.json'
import countries from '../../assets/countries.json'
import { TextButton, SelectField, ButtonLink, CheckboxField, TextField } from '@ropescore/components'
import { useHead } from '@vueuse/head'
import { usePodium } from '../hooks/podium'
import PhotoPicker from '../components/PhotoPicker.vue'
import { useTheme } from '../hooks/theme'
import { usePodium } from './use-podium'
import PhotoPicker from '../../components/PhotoPicker.vue'
import { useTheme } from '../../hooks/theme'
useHead({
title: 'Podium'
Expand Down
6 changes: 3 additions & 3 deletions src/views/PodiumLive.vue → src/views/podium/Display.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@
<script lang="ts" setup>
import { ref, watch } from 'vue'
import { useHead } from '@vueuse/head'
import { usePodium, type PodiumSettings } from '../hooks/podium'
import { getOpfsImgUrl } from '../helpers'
import { useTheme } from '../hooks/theme'
import { usePodium, type PodiumSettings } from './use-podium'
import { getOpfsImgUrl } from '../../helpers'
import { useTheme } from '../../hooks/theme'
useHead({
title: '📺 Podium (Live)'
Expand Down
File renamed without changes.
135 changes: 135 additions & 0 deletions src/views/qualifiers/Config.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<template>
<div class="mb-4 mx-auto container flex justify-between">
<div>
<text-button color="blue" @click="bc.postMessage('show')">
Show
</text-button>
<text-button color="orange" @click="bc.postMessage('hide')">
Hide
</text-button>
</div>
<button-link
:to="`/qualifiers/display?theme=${theme}`"
>
Display
</button-link>
</div>

<div class="mx-auto container grid grid-cols-[max-content] items-center justify-center mt-8">
<div>
<text-field
v-model="settings.title"
label="Title (Event name)"
/>
<text-field
v-model="settings.subTitle"
label="Subtitle (Gender category)"
/>
</div>

<div class="self-center">
<photo-picker
v-model="settings.background"
label="Background image"
/>
</div>
</div>

<div class="mx-auto container flex flex-col gap-4 items-center justify-center mt-8">
<text-button
color="blue"
class="self-end"
@click="newQualifier()"
>
New Qualifier
</text-button>

<div v-for="qualifier of qualifiers" :key="qualifier.id" class="w-full border-b mb-4 pb-4">
<div class="flex justify-end">
<text-button
color="red"
@click="removeQualifier(qualifier.id)"
>
Remove Qualifier
</text-button>
</div>

<select-field
v-model="qualifier.countryCode"
label="Country"
:data-list="countriesList"
/>

<div
v-for="name, idx of qualifier.names"
:id="`name-${qualifier.id}-${idx}`"
:key="idx"
>
<text-field
:model-value="name"
:label="`Name ${idx + 1}`"
@update:model-value="updateName(qualifier, idx, $event)"
/>
</div>

<div
:id="`name-${qualifier.id}-new`"
>
<text-field
v-model="newName"
label="New Name"
@update:model-value="addName(qualifier, $event)"
/>
</div>
</div>
</div>
</template>

<script lang="ts" setup>
import { useHead } from '@vueuse/head'
import countries from '../../assets/countries.json'
import { ButtonLink, TextField, TextButton, SelectField } from '@ropescore/components'
import { useTheme } from '../../hooks/theme'
import { useQualifiers, type Qualifier } from './use-qualifiers'
import PhotoPicker from '../../components/PhotoPicker.vue'
import { nextTick, ref } from 'vue'
useHead({
title: 'Qualifiers'
})
const theme = useTheme()
const { settings, qualifiers } = useQualifiers()
const bc = new BroadcastChannel('rs-qualifiers')
const countriesList = countries.map(c => ({ text: c.name, value: c.code }))
function newQualifier () {
qualifiers.value.push({ id: crypto.randomUUID(), names: [] })
}
function removeQualifier (id: string) {
const idx = qualifiers.value.findIndex(q => q.id === id)
if (idx !== -1) qualifiers.value.splice(idx, 1)
}
function updateName (qualifier: Qualifier, nameIdx: number, name: string | number) {
if (typeof name !== 'string' || name == null || name.trim() === '') {
qualifier.names.splice(nameIdx, 1)
const next = document.querySelector<HTMLInputElement>(`#name-${qualifier.id}-${nameIdx - 1} input`) ??
document.querySelector<HTMLInputElement>(`#name-${qualifier.id}-new input`)
next?.focus()
} else {
qualifier.names.splice(nameIdx, 1, name)
}
}
const newName = ref('')
function addName (qualifier: Qualifier, name: string | number) {
if (typeof name !== 'string') return
qualifier.names.push(name)
nextTick(() => {
document.querySelector<HTMLInputElement>(`#name-${qualifier.id}-${qualifier.names.length - 1} input`)?.focus()
newName.value = ''
})
}
</script>
Loading

0 comments on commit 2cb4102

Please sign in to comment.