Skip to content

Commit

Permalink
Merge pull request #2 from krazkidd:pinia
Browse files Browse the repository at this point in the history
Encapsulate app state in a Pinia store
  • Loading branch information
krazkidd authored Sep 7, 2023
2 parents a186c33 + ba160ee commit 3e3b76a
Show file tree
Hide file tree
Showing 11 changed files with 329 additions and 190 deletions.
44 changes: 10 additions & 34 deletions components/lineup/Lineup.vue
Original file line number Diff line number Diff line change
@@ -1,73 +1,49 @@
<script setup lang="ts">
import { useSortable } from '@vueuse/integrations/useSortable'
import { nanoid } from 'nanoid';
import { useAppSettingsStore } from '~~/stores/AppSettings'
import type { Spot, Lineup, AppSettings } from '~~/types';
const lineup = useLocalStorage<Lineup>('lineup', {
id: nanoid(),
teamName: '',
spots: []
}, {
mergeDefaults: true
});
const appSettings = useLocalStorage<AppSettings>('app-settings', {
isLineupLocked: false,
jerseyColor: 'f47373',
jerseyTextColor: '000000'
}, {
mergeDefaults: true
});
const appSettingsStore = useAppSettingsStore();
const sortableContainer = ref<HTMLElement | null>(null);
useSortable(sortableContainer, lineup.value.spots, {
useSortable(sortableContainer, appSettingsStore.getSpots, {
group: 'spots',
handle: '.drag-handle',
animation: 150,
onMove: () => !appSettings.value.isLineupLocked
onMove: () => !appSettingsStore.getIsLocked
});
function addSpot(spot: Spot) {
if (!appSettings.value.isLineupLocked) {
lineup.value.spots.push(spot);
}
}
</script>

<template>
<div class="p-5 rounded w-full md:w-3/4 xl:w-1/2">
<header class="flex font-bold mb-4">
<input
type="text"
v-model.trim="lineup.teamName"
@change.trim="appSettingsStore.getTeamName"
@keyup.enter="($event.target as HTMLInputElement).blur()"
class="grow inline-block overflow-x-hidden text-ellipsis bg-transparent focus:shadow rounded text-gray-700 placeholder-gray-500 dark:text-gray-300 leading-[3em] cursor-pointer px-1"
placeholder="Team Name"
/>

<SettingsLockButton :is-locked="appSettings.isLineupLocked" @lock="appSettings.isLineupLocked = true" @unlock="appSettings.isLineupLocked = false" />
<SettingsLockButton />

<SettingsButton :app-settings="appSettings" />
<SettingsButton />
</header>

<div ref="sortableContainer">
<ClientOnly>
<LineupSpot
v-for="spot in lineup.spots"
v-for="spot in appSettingsStore.getSpots"
:key="spot.player.id"
:spot="spot"
:is-lineup-locked="appSettings.isLineupLocked"
:jersey-color="appSettings.jerseyColor"
:jersey-text-color="appSettings.jerseyTextColor"
@delete="lineup.spots = lineup.spots.filter(s => s.player.id !== $event)"
@delete="appSettingsStore.removeSpot($event)"
class="bg-blue-200"
/>
</ClientOnly>
</div>

<footer>
<LineupNewSpot @add="addSpot($event)" :class="`${ appSettings.isLineupLocked ? 'collapse' : 'visible' }`" />
<LineupNewSpot @add="appSettingsStore.addSpot($event)" :class="`${ appSettingsStore.getIsLocked ? 'collapse' : 'visible' }`" />
</footer>
</div>
</template>
Expand Down
11 changes: 6 additions & 5 deletions components/lineup/LineupSpot.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<script setup lang="ts">
import { useAppSettingsStore } from '~~/stores/AppSettings'
import type { ID, Spot } from '~~/types';
import { PositionOptions } from '~~/types';
const appSettingsStore = useAppSettingsStore();
const props = defineProps<{
spot: Spot,
isLineupLocked: boolean,
jerseyColor: string,
jerseyTextColor: string
}>();
const emit = defineEmits<{
Expand All @@ -31,9 +32,9 @@ const isPositionDialogVisible = ref(false);
@blur="focused = false"
tabindex="0"
>
<LineupDragHandle :class="`${ props.isLineupLocked ? 'collapse' : 'visible' } inline-block shrink-0 text-[1.3em] px-2`" />
<LineupDragHandle :class="`${ appSettingsStore.getIsLocked ? 'collapse' : 'visible' } inline-block shrink-0 text-[1.3em] px-2`" />

<PlayerJersey :player="props.spot.player" :jersey-color="props.jerseyColor" :jersey-text-color="props.jerseyTextColor" class="shrink-0" />
<PlayerJersey :player="props.spot.player" class="shrink-0" />

<input
type="text"
Expand Down
10 changes: 6 additions & 4 deletions components/player/PlayerJersey.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
<script setup lang="ts">
import { useAppSettingsStore } from '~~/stores/AppSettings'
import type { Player } from '~~/types';
const appSettingsStore = useAppSettingsStore();
const props = defineProps<{
player: Player,
jerseyColor: string,
jerseyTextColor: string
}>();
</script>

<template>
<svg viewBox="215 45 526.2 372.045" width="3em" height="3em" xmlns="http://www.w3.org/2000/svg">
<use x="-308.27" href="@/assets/images/cloth-t-shirt.svg#shirt-back" :fill="`#${ props.jerseyColor }`" />
<text x="390" y="200" font-size="10em" :fill="`#${ props.jerseyTextColor }`">{{ props.player.number }}</text>
<use x="-308.27" href="@/assets/images/cloth-t-shirt.svg#shirt-back" :fill="`#${ appSettingsStore.getJerseyColor }`" />
<text x="390" y="200" font-size="10em" :fill="`#${ appSettingsStore.getJerseyTextColor }`">{{ props.player.number }}</text>
</svg>
</template>

Expand Down
20 changes: 8 additions & 12 deletions components/settings/SettingsButton.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
<script setup lang="ts">
import type { AppSettings } from '~~/types';
import { useAppSettingsStore } from '~~/stores/AppSettings';
const props = defineProps<{
appSettings: AppSettings
}>();
const mode = useColorMode();
const appSettingsStore = useAppSettingsStore();
const isSettingsDialogVisible = ref(false);
</script>
Expand All @@ -30,22 +26,22 @@ const isSettingsDialogVisible = ref(false);
</div>
<div class="md:col-span-3">
<Button
@click="mode.preference = mode.preference === 'system' ? 'dark' : mode.preference === 'dark' ? 'light' : 'system'"
@click="appSettingsStore.setColorMode(appSettingsStore.getColorMode === 'system' ? 'dark' : appSettingsStore.getColorMode === 'dark' ? 'light' : 'system')"
size="small"
severity="primary"
rounded
aria-label="Color mode"
title="Color mode"
>
<template v-if="mode.preference === 'system'">
<template v-if="appSettingsStore.getColorMode === 'system'">
<i class="pi pi-desktop pr-2"></i>
System
</template>
<template v-if="mode.preference === 'dark'">
<template v-if="appSettingsStore.getColorMode === 'dark'">
<i class="pi pi-moon pr-2"></i>
Dark
</template>
<template v-if="mode.preference === 'light'">
<template v-if="appSettingsStore.getColorMode === 'light'">
<i class="pi pi-sun pr-2"></i>
Light
</template>
Expand All @@ -56,14 +52,14 @@ const isSettingsDialogVisible = ref(false);
Jersey Color
</div>
<div>
<ColorPicker v-model="props.appSettings.jerseyColor" format="hex" />
<ColorPicker :modelValue="appSettingsStore.getJerseyColor" @update:modelValue="appSettingsStore.setJerseyColor($event as unknown as string)" format="hex" />
</div>

<div class="text-right text-xs py-2">
Jersey Text Color
</div>
<div>
<ColorPicker v-model="props.appSettings.jerseyTextColor" format="hex" />
<ColorPicker :modelValue="appSettingsStore.getJerseyTextColor" @update:modelValue="appSettingsStore.setJerseyTextColor($event as unknown as string)" format="hex" />
</div>
</div>
</Dialog>
Expand Down
31 changes: 7 additions & 24 deletions components/settings/SettingsLockButton.vue
Original file line number Diff line number Diff line change
@@ -1,34 +1,17 @@
<script setup lang="ts">
const props = defineProps<{
isLocked: boolean
}>();
import { useAppSettingsStore } from '~~/stores/AppSettings'
const emit = defineEmits<{
(e: "lock"): void;
(e: "unlock"): void;
}>();
const isLocked = ref(props.isLocked);
function handleClick(): void {
isLocked.value = !isLocked.value;
if (isLocked.value) {
emit('lock');
} else {
emit('unlock');
}
}
const appSettingsStore = useAppSettingsStore();
</script>

<template>
<Button
@click="handleClick"
:icon="`pi pi-${ isLocked ? 'lock' : 'lock-open' }`"
:severity="`${ isLocked ? 'secondary' : 'warning' }`"
@click="appSettingsStore.setIsLocked(!appSettingsStore.getIsLocked)"
:icon="`pi pi-${ appSettingsStore.getIsLocked ? 'lock' : 'lock-open' }`"
:severity="`${ appSettingsStore.getIsLocked ? 'secondary' : 'warning' }`"
text
rounded
:aria-label="`${ isLocked ? 'Unlock lineup' : 'Lock lineup' }`"
:title="`${ isLocked ? 'Unlock lineup' : 'Lock lineup' }`"
:aria-label="`${ appSettingsStore.getIsLocked ? 'Unlock lineup' : 'Lock lineup' }`"
:title="`${ appSettingsStore.getIsLocked ? 'Unlock lineup' : 'Lock lineup' }`"
/>
</template>
1 change: 1 addition & 0 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export default defineNuxtConfig({
modules: [
"@nuxtjs/color-mode",
"@nuxtjs/tailwindcss",
"@pinia/nuxt",
"@vueuse/nuxt"
],
css: [
Expand Down
Loading

0 comments on commit 3e3b76a

Please sign in to comment.