Skip to content

Commit

Permalink
Merge pull request #4 from krazkidd/scoreboard-firestore
Browse files Browse the repository at this point in the history
  • Loading branch information
krazkidd authored Sep 22, 2023
2 parents ca2b6e3 + e6cdaeb commit f577676
Show file tree
Hide file tree
Showing 37 changed files with 1,670 additions and 466 deletions.
5 changes: 5 additions & 0 deletions .firebaserc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"projects": {
"default": "lineup-d5a4d"
}
}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ logs
.env
.env.*
!.env.example
service-account.json
.firebase
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ License: AGPLv3 (see LICENSE.md file)
* Customizable team colors
* Dark mode

The app can be used without an active internet connection by making use of local browser storage. (This may change in the future.)

## Development

### VS Code Recommended Extensions:
Expand Down Expand Up @@ -75,4 +73,4 @@ An app spec is available under `.do/` which will run the SSG command and publish

## Attributions

The softball favicon (`public/favicon.ico`) is used under the [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/) license from the [twemoji](https://github.com/twitter/twemoji) project. The source image is [here](https://github.com/twitter/twemoji/blob/master/assets/svg/1f94e.svg).
The softball favicon (`public/favicon/favicon.ico`) is used under the [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/) license from the [twemoji](https://github.com/twitter/twemoji) project.
104 changes: 99 additions & 5 deletions app.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,105 @@
<script setup lang="ts">
import { useAppSettingsStore } from '~~/stores/AppSettings';
const appSettingsStore = useAppSettingsStore();
const homeRoute = ref({
label: 'Home',
icon: 'pi pi-fw pi-home',
route: '/'
});
const menuItems = ref([
homeRoute.value,
{
label: 'Lineup',
icon: 'pi pi-fw pi-user-edit',
route: '/lineup'
},
{
label: 'Scoreboard',
icon: 'pi pi-fw pi-play',
route: '/scoreboard'
},
]);
const isSidebarVisible = ref(false);
const sidebarPassThroughOptions = {
headerContent: {
class: 'flex items-start w-full'
},
content: {
class: 'flex flex-col justify-between w-full md:w-20rem lg:w-30rem'
}
};
const menuPassThroughOptions = {
root: {
class: 'w-full'
}
};
</script>

<template>
<Sidebar v-model:visible="isSidebarVisible" position="right" :pt="sidebarPassThroughOptions">
<template #header>
<Button
@click="appSettingsStore.colorMode = appSettingsStore.colorMode === 'system' ? 'dark' : appSettingsStore.colorMode === 'dark' ? 'light' : 'system'"
class="text-gray-800 border-gray-800 dark:text-gray-300 dark:border-gray-300"
size="small"
outlined
aria-label="Color mode"
title="Color mode"
>
<template v-if="appSettingsStore.colorMode === 'system'">
<i class="pi pi-fw pi-desktop pr-2"></i>
System
</template>
<template v-if="appSettingsStore.colorMode === 'dark'">
<i class="pi pi-fw pi-moon pr-2"></i>
Dark
</template>
<template v-if="appSettingsStore.colorMode === 'light'">
<i class="pi pi-fw pi-sun pr-2"></i>
Light
</template>
</Button>
</template>

<template #default>
<Menu :model="menuItems" :pt="menuPassThroughOptions">
<template #item="{ label, item, props }">
<RouterLink :to="item.route" v-slot="{ href, route, navigate, isActive, isExactActive }" custom>
<a :href="href" v-bind="props.action" @click="navigate" :class="[isActive && 'router-link-active', isExactActive && 'router-link-exact-active']">
<span v-bind="props.icon" />
<span v-bind="props.label">{{ label }}</span>
</a>
</RouterLink>
</template>
</Menu>

<div class="justify-self-end text-sm">
This program is licensed to you for use under the <a href="https://www.gnu.org/licenses/agpl.html" class="underline">GNU AGPL v3</a>. <a href="https://github.com/krazkidd/lineup"><i class="pi pi-github" /></a>
</div>
</template>
</Sidebar>

<div class="flex flex-col items-center min-h-screen">
<!-- <nav class="flex items-end p-2 space-x-2">
</nav> -->
<div class="flex justify-between items-center w-full p-1">
<RouterLink :to="homeRoute.route" :title="homeRoute.label" class="inline-block p-2">
<img src="@/favicon/favicon-32x32.png" :alt="homeRoute.label" />
</RouterLink>

<Lineup class="grow justify-center w-full md:w-3/4 xl:w-1/2 p-5" />
<Button
@click="isSidebarVisible = true"
icon="pi pi-bars"
severity="secondary"
text
title="Menu"
/>
</div>

<div class="text-center text-sm pt-10">
This program is licensed to you for use under the <a href="https://www.gnu.org/licenses/agpl.html" class="underline">GNU AGPL v3</a>. <a href="https://github.com/krazkidd/lineup"><i class="pi pi-github" /></a>
<div class="grow justify-center w-full md:w-3/4 xl:w-1/2 p-5">
<NuxtPage />
</div>
</div>
</template>
Expand All @@ -27,4 +117,8 @@ body {
input {
@apply placeholder-gray-600 dark:placeholder-gray-400;
}
.router-link-exact-active {
@apply text-orange-600 dark:text-yellow-300;
}
</style>
60 changes: 0 additions & 60 deletions components/lineup/Lineup.vue

This file was deleted.

22 changes: 14 additions & 8 deletions components/lineup/LineupJerseyButton.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
<script setup lang="ts">
import { useAppSettingsStore } from '~~/stores/AppSettings'
import { useTeamStore } from '~~/stores/Team';
import { getTeam } from '~~/db/Team';
import { getLineup, updateSpot } from '~~/db/Lineup';
import type { Spot } from '~~/types';
const appSettingsStore = useAppSettingsStore();
const db = useFirestore();
const teamStore = useTeamStore();
const { data: team } = useDocument(await getTeam(db, teamStore.id));
const { data: lineup } = useDocument(await getLineup(db, teamStore.id));
const props = defineProps<{
spot: Spot,
Expand All @@ -16,11 +21,11 @@ const isDialogVisible = ref(false);
<template>
<div @click="isDialogVisible = true">
<svg viewBox="215 45 526.2 372.045" :width="props.size" :height="props.size" xmlns="http://www.w3.org/2000/svg">
<use x="-308.27" href="@/assets/images/cloth-t-shirt.svg#shirt-back" :fill="`#${ appSettingsStore.jerseyColor }`" />
<use x="-308.27" href="@/assets/images/cloth-t-shirt.svg#shirt-back" :fill="`#${ team?.jerseyColor }`" />

<text v-if="props.spot.player.number.length === 1" x="445" y="200" font-size="10em" font-weight="bold" :fill="`#${ appSettingsStore.jerseyTextColor }`">{{ props.spot.player.number }}</text>
<text v-else-if="props.spot.player.number.length === 2" x="390" y="200" font-size="10em" font-weight="bold" :fill="`#${ appSettingsStore.jerseyTextColor }`">{{ props.spot.player.number }}</text>
<text v-else-if="props.spot.player.number.length === 3" x="370" y="200" font-size="8.5em" font-weight="bold" :fill="`#${ appSettingsStore.jerseyTextColor }`">{{ props.spot.player.number }}</text>
<text v-if="props.spot.player.number.length === 1" x="445" y="200" font-size="10em" font-weight="bold" :fill="`#${ team?.jerseyTextColor }`">{{ props.spot.player.number }}</text>
<text v-else-if="props.spot.player.number.length === 2" x="390" y="200" font-size="10em" font-weight="bold" :fill="`#${ team?.jerseyTextColor }`">{{ props.spot.player.number }}</text>
<text v-else-if="props.spot.player.number.length === 3" x="370" y="200" font-size="8.5em" font-weight="bold" :fill="`#${ team?.jerseyTextColor }`">{{ props.spot.player.number }}</text>
</svg>

<Dialog
Expand All @@ -35,7 +40,8 @@ const isDialogVisible = ref(false);
<div class="flex flex-column gap-2">
<InputText
type="text"
v-model="props.spot.player.number"
:model-value="props.spot.player.number"
@update:model-value="updateSpot(lineup!.spots, { player: { ...props.spot.player, number: $event }, position: props.spot.position })"
@keyup.enter="isDialogVisible = false"
:pt="{
root: { class: '!w-full' },
Expand Down
3 changes: 1 addition & 2 deletions components/lineup/LineupNewSpot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ function createSpot(e: Event) {
e.preventDefault();
emit("add", {
id: nanoid(),
player: {
id: nanoid(),
name: playerName.value,
Expand All @@ -47,7 +46,7 @@ function createSpot(e: Event) {
class="grow inline-block bg-transparent focus:shadow rounded cursor-pointer px-1 py-2"
@focus="focused = true"
@blur="focused = false"
:placeholder="!focused ? '+ Add A Player' : 'Enter player name'"
:placeholder="focused ? 'Enter player name' : '+ Add A Player'"
/>

<div class="shrink-0 px-1 py-2">
Expand Down
10 changes: 9 additions & 1 deletion components/lineup/LineupPositionButton.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
<script lang="ts" setup>
import { useTeamStore } from '~~/stores/Team';
import { getLineup, updateSpot } from '~~/db/Lineup';
import type { Spot } from '~~/types';
import { PositionOptions, getPositionShortName, getPositionLongName } from '~~/types';
const db = useFirestore();
const teamStore = useTeamStore();
const { data: lineup } = useDocument(await getLineup(db, teamStore.id));
const props = defineProps<{
spot: Spot
}>();
Expand All @@ -28,7 +35,8 @@ const positionLongName = computed(() => getPositionLongName(props.spot.position)
}"
>
<Listbox
v-model="props.spot.position"
:model-value="props.spot.position"
@update:model-value="updateSpot(lineup!.spots, { ...props.spot, position: $event })"
:options="PositionOptions"
option-group-label="groupName"
option-group-children="children"
Expand Down
14 changes: 7 additions & 7 deletions components/lineup/LineupSpot.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script setup lang="ts">
import { useAppSettingsStore } from '~~/stores/AppSettings'
import { useTeamStore } from '~~/stores/Team'
import type { ID, Spot } from '~~/types';
const appSettingsStore = useAppSettingsStore();
const teamStore = useTeamStore();
const props = defineProps<{
spot: Spot,
Expand All @@ -15,7 +15,7 @@ const emit = defineEmits<{
const focused = ref(false);
onKeyStroke("Backspace", (e) => {
if (focused.value && !appSettingsStore.isLocked) {
if (focused.value && !teamStore.isLocked) {
emit('delete', props.spot.player.id);
}
});
Expand All @@ -29,13 +29,13 @@ onKeyStroke("Backspace", (e) => {
@blur="focused = false"
tabindex="0"
>
<LineupDragHandle :class="`${ appSettingsStore.isLocked ? 'collapse' : 'visible' } inline-block shrink-0 text-[1.3em] px-2`" />
<LineupDragHandle :class="`${ teamStore.isLocked ? 'collapse' : 'visible' } inline-block shrink-0 text-[1.3em] px-2`" />

<LineupJerseyButton
:spot="props.spot"
:size="'3em'"
:class="`shrink-0 inline-block cursor-pointer hover:outline hover:outline-blue-950 rounded-full w-[3em] pointer-events-${appSettingsStore.isLocked ? 'none' : 'auto'}`"
:disabled="appSettingsStore.isLocked"
:class="`shrink-0 inline-block cursor-pointer hover:outline hover:outline-blue-950 rounded-full w-[3em] pointer-events-${teamStore.isLocked ? 'none' : 'auto'}`"
:disabled="teamStore.isLocked"
/>

<input
Expand All @@ -44,7 +44,7 @@ onKeyStroke("Backspace", (e) => {
@keyup.enter="($event.target as HTMLInputElement).blur()"
class="grow inline-block overflow-x-hidden text-ellipsis bg-transparent focus:shadow rounded placeholder-gray-500 dark:placeholder-gray-500 cursor-pointer px-1"
placeholder="Enter player name"
:disabled="appSettingsStore.isLocked"
:disabled="teamStore.isLocked"
/>

<LineupPositionButton
Expand Down
Loading

0 comments on commit f577676

Please sign in to comment.