Skip to content

Commit

Permalink
Turn SSR off and use Pinia store as recommended (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
krazkidd authored Sep 7, 2023
1 parent 3e3b76a commit 36bf537
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 199 deletions.
10 changes: 5 additions & 5 deletions components/lineup/Lineup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import { useAppSettingsStore } from '~~/stores/AppSettings'
const appSettingsStore = useAppSettingsStore();
const sortableContainer = ref<HTMLElement | null>(null);
useSortable(sortableContainer, appSettingsStore.getSpots, {
useSortable(sortableContainer, appSettingsStore.spots, {
group: 'spots',
handle: '.drag-handle',
animation: 150,
onMove: () => !appSettingsStore.getIsLocked
onMove: () => !appSettingsStore.isLocked
});
</script>

Expand All @@ -19,7 +19,7 @@ useSortable(sortableContainer, appSettingsStore.getSpots, {
<header class="flex font-bold mb-4">
<input
type="text"
@change.trim="appSettingsStore.getTeamName"
v-model.trim="appSettingsStore.teamName"
@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"
Expand All @@ -33,7 +33,7 @@ useSortable(sortableContainer, appSettingsStore.getSpots, {
<div ref="sortableContainer">
<ClientOnly>
<LineupSpot
v-for="spot in appSettingsStore.getSpots"
v-for="spot in appSettingsStore.spots"
:key="spot.player.id"
:spot="spot"
@delete="appSettingsStore.removeSpot($event)"
Expand All @@ -43,7 +43,7 @@ useSortable(sortableContainer, appSettingsStore.getSpots, {
</div>

<footer>
<LineupNewSpot @add="appSettingsStore.addSpot($event)" :class="`${ appSettingsStore.getIsLocked ? 'collapse' : 'visible' }`" />
<LineupNewSpot @add="appSettingsStore.addSpot($event)" :class="`${ appSettingsStore.isLocked ? 'collapse' : 'visible' }`" />
</footer>
</div>
</template>
Expand Down
2 changes: 1 addition & 1 deletion components/lineup/LineupSpot.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const isPositionDialogVisible = ref(false);
@blur="focused = false"
tabindex="0"
>
<LineupDragHandle :class="`${ appSettingsStore.getIsLocked ? 'collapse' : 'visible' } inline-block shrink-0 text-[1.3em] px-2`" />
<LineupDragHandle :class="`${ appSettingsStore.isLocked ? 'collapse' : 'visible' } inline-block shrink-0 text-[1.3em] px-2`" />

<PlayerJersey :player="props.spot.player" class="shrink-0" />

Expand Down
4 changes: 2 additions & 2 deletions components/player/PlayerJersey.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ const props = defineProps<{

<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="`#${ appSettingsStore.getJerseyColor }`" />
<text x="390" y="200" font-size="10em" :fill="`#${ appSettingsStore.getJerseyTextColor }`">{{ props.player.number }}</text>
<use x="-308.27" href="@/assets/images/cloth-t-shirt.svg#shirt-back" :fill="`#${ appSettingsStore.jerseyColor }`" />
<text x="390" y="200" font-size="10em" :fill="`#${ appSettingsStore.jerseyTextColor }`">{{ props.player.number }}</text>
</svg>
</template>

Expand Down
12 changes: 6 additions & 6 deletions components/settings/SettingsButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,22 @@ const isSettingsDialogVisible = ref(false);
</div>
<div class="md:col-span-3">
<Button
@click="appSettingsStore.setColorMode(appSettingsStore.getColorMode === 'system' ? 'dark' : appSettingsStore.getColorMode === 'dark' ? 'light' : 'system')"
@click="appSettingsStore.colorMode = appSettingsStore.colorMode === 'system' ? 'dark' : appSettingsStore.colorMode === 'dark' ? 'light' : 'system'"
size="small"
severity="primary"
rounded
aria-label="Color mode"
title="Color mode"
>
<template v-if="appSettingsStore.getColorMode === 'system'">
<template v-if="appSettingsStore.colorMode === 'system'">
<i class="pi pi-desktop pr-2"></i>
System
</template>
<template v-if="appSettingsStore.getColorMode === 'dark'">
<template v-if="appSettingsStore.colorMode === 'dark'">
<i class="pi pi-moon pr-2"></i>
Dark
</template>
<template v-if="appSettingsStore.getColorMode === 'light'">
<template v-if="appSettingsStore.colorMode === 'light'">
<i class="pi pi-sun pr-2"></i>
Light
</template>
Expand All @@ -52,14 +52,14 @@ const isSettingsDialogVisible = ref(false);
Jersey Color
</div>
<div>
<ColorPicker :modelValue="appSettingsStore.getJerseyColor" @update:modelValue="appSettingsStore.setJerseyColor($event as unknown as string)" format="hex" />
<ColorPicker v-model="appSettingsStore.jerseyColor" format="hex" />
</div>

<div class="text-right text-xs py-2">
Jersey Text Color
</div>
<div>
<ColorPicker :modelValue="appSettingsStore.getJerseyTextColor" @update:modelValue="appSettingsStore.setJerseyTextColor($event as unknown as string)" format="hex" />
<ColorPicker v-model="appSettingsStore.jerseyTextColor" format="hex" />
</div>
</div>
</Dialog>
Expand Down
10 changes: 5 additions & 5 deletions components/settings/SettingsLockButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ const appSettingsStore = useAppSettingsStore();

<template>
<Button
@click="appSettingsStore.setIsLocked(!appSettingsStore.getIsLocked)"
:icon="`pi pi-${ appSettingsStore.getIsLocked ? 'lock' : 'lock-open' }`"
:severity="`${ appSettingsStore.getIsLocked ? 'secondary' : 'warning' }`"
@click="appSettingsStore.isLocked = !appSettingsStore.isLocked"
:icon="`pi pi-${ appSettingsStore.isLocked ? 'lock' : 'lock-open' }`"
:severity="`${ appSettingsStore.isLocked ? 'secondary' : 'warning' }`"
text
rounded
:aria-label="`${ appSettingsStore.getIsLocked ? 'Unlock lineup' : 'Lock lineup' }`"
:title="`${ appSettingsStore.getIsLocked ? 'Unlock lineup' : 'Lock lineup' }`"
:aria-label="`${ appSettingsStore.isLocked ? 'Unlock lineup' : 'Lock lineup' }`"
:title="`${ appSettingsStore.isLocked ? 'Unlock lineup' : 'Lock lineup' }`"
/>
</template>
3 changes: 3 additions & 0 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ export default defineNuxtConfig({
"@pinia/nuxt",
"@vueuse/nuxt"
],
// HACK: We have to disable SSR until Pinia has better
// support for our usage. See stores/AppSettings.ts.
ssr: false,
css: [
'primevue/resources/themes/saga-blue/theme.css',
'primevue/resources/primevue.css',
Expand Down
129 changes: 72 additions & 57 deletions stores/AppSettings.ts
Original file line number Diff line number Diff line change
@@ -1,82 +1,97 @@
import { defineStore, acceptHMRUpdate } from "pinia";
import { defineStore, skipHydrate, acceptHMRUpdate } from "pinia";
import { nanoid } from "nanoid";

import type { Spot } from '~~/types';
import type { Spot, Lineup } from '~~/types';

// HACK: Unfortunately, we were not able to expose any state properties
// because we could not enforce writes to be replicated to the
// persistent local storage. Specifically, we were not able to
// do so under Nuxt's server-side rendering scheme. (With SSR turned
// off or with the experimental `renderJsonPayloads: false` flag,
// it may work.)
//
// For performance reasons, we store all the values we want separately
// instead of as a larger JSON object.
// NOTE: This Pinia store requires `ssr: false` in `nuxt.config.*` because the server
// will try to serialize our computed state properties to JSON, and that will fail
// because functions can't be serialized.
//
// See: [The Pinia guide](https://pinia.vuejs.org/core-concepts/)
// https://github.com/vuejs/pinia/issues/829 (look for "Advanced SSR")
// https://github.com/vuejs/pinia/issues/447#issuecomment-1455285437
// https://github.com/nuxt/nuxt/issues/20889

export const useAppSettingsStore = defineStore('AppSettingsStore', {
// state: () => {
// function $reset() {
// //TODO
// }

// return {
// $reset,
// };
// },
actions: {
setColorMode(v: string) {
const mode = useColorMode();
state: () => {
const _colorMode = useColorMode();

mode.preference = v;
},
const defaults = {
id: nanoid(),

setTeamName(v: string) {
const store = useLocalStorage('AppSettingsStore:teamName', '');
teamName: '',
jerseyColor: 'f47373',
jerseyTextColor: '000000',

store.value = v;
},
setJerseyColor(v: string) {
const store = useLocalStorage('AppSettingsStore:jerseyColor', '');
isLocked: false,
spots: [],
};

store.value = v;
},
setJerseyTextColor(v: string) {
const store = useLocalStorage('AppSettingsStore:jerseyTextColor', '');
const _lineup = useLocalStorage<Lineup>('AppSettingsStore:lineup', defaults, { mergeDefaults: true });

store.value = v;
},
// NOTE: We provide setters so we can persist to storage.
// Source: https://github.com/vuejs/pinia/issues/447#issuecomment-1455285437

setIsLocked(v: boolean) {
const store = useLocalStorage('AppSettingsStore:isLocked', false);
const colorMode = computed<string>({
get: () => _colorMode.preference,
set: (v) => _colorMode.preference = v
});

store.value = v;
},
addSpot(spot: Spot) {
const store = useLocalStorage('AppSettingsStore:spots', [] as Array<Spot>);
const teamName = computed<string>({
get: () => _lineup.value.teamName,
set: (v) => _lineup.value.teamName = v
});

const jerseyColor = computed<string>({
get: () => _lineup.value.jerseyColor,
set: (v) => _lineup.value.jerseyColor = v
});

const jerseyTextColor = computed<string>({
get: () => _lineup.value.jerseyTextColor,
set: (v) => _lineup.value.jerseyTextColor = v
});

const isLocked = computed<boolean>({
get: () => _lineup.value.isLocked,
set: (v) => _lineup.value.isLocked = v
});

if (!this.getIsLocked) {
store.value.push({ ...spot });
const spots = computed<Spot[]>({
get: () => _lineup.value.spots,
set: (v) => _lineup.value.spots = v
});

// function $reset() {
// //TODO
// }

return {
colorMode: skipHydrate(colorMode),

teamName: skipHydrate(teamName),
jerseyColor: skipHydrate(jerseyColor),
jerseyTextColor: skipHydrate(jerseyTextColor),

isLocked: skipHydrate(isLocked),
spots: skipHydrate(spots),

//$reset,
};
},
actions: {
addSpot(spot: Spot) {
if (!this.isLocked) {
this.spots.push({ ...spot });
}
},
removeSpot(playerId: string) {
const store = useLocalStorage('AppSettingsStore:spots', [] as Array<Spot>);

store.value = store.value.filter(s => s.player.id !== playerId);
this.spots = this.spots.filter(s => s.player.id !== playerId)
},
},
getters: {
getColorMode: state => useColorMode().preference,

getTeamName: state => useLocalStorage('AppSettingsStore:teamName', '').value,
getJerseyColor: state => useLocalStorage('AppSettingsStore:jerseyColor', 'f47373').value,
getJerseyTextColor: state => useLocalStorage('AppSettingsStore:jerseyTextColor', '000000').value,
// getters: {

getIsLocked: state => useLocalStorage('AppSettingsStore:isLocked', false).value,
getSpots: state => useLocalStorage('AppSettingsStore:spots', [] as Array<Spot>).value,
}
// }
});

if (import.meta.hot) {
Expand Down
Loading

0 comments on commit 36bf537

Please sign in to comment.