Skip to content

Commit

Permalink
chore: add input constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
qcp committed Feb 10, 2024
1 parent 09f4ca2 commit 28e3d00
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 77 deletions.
49 changes: 0 additions & 49 deletions src/components/GameSettings.vue

This file was deleted.

82 changes: 67 additions & 15 deletions src/components/SettingsDialog.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
<script setup lang="ts">
import type { IVoteSystems } from '@/constants/voteSystem'
const voteSystemOptions = computed(() =>
VoteSystems.map(name => ({
name,
description: VoteSystemConfig[name].description,
})),
)
const gameName = defineModel<string>('gameName')
const voteSystemName = defineModel<IVoteSystems>('voteSystemName')
Expand All @@ -9,6 +16,24 @@ const voteSystemNameDraft = ref<IVoteSystems>('fibonachi')
const [visible, toggle] = useToggle()
const constraint = computed(() => {
const errors = new Map<'gameName' | 'voteSystemName', string>()
const gameName = gameNameDraft.value?.trim()
if (!gameName) {
errors.set('gameName', `Name must be non empty`)
}
else if (gameName.length < 3) {
errors.set('gameName', `Name must be at least 3 symbol length`)
}
else if (gameName.length > 15) {
errors.set('gameName', `Name must be less 15 symbol length`)
}
if (!voteSystemNameDraft.value) {
errors.set('voteSystemName', `Select prefered vote system`)
}
return errors
})
watch(
gameName,
() => {
Expand All @@ -19,7 +44,7 @@ watch(
{ immediate: true },
)
watch(
gameName,
voteSystemName,
() => {
if (voteSystemName.value) {
voteSystemNameDraft.value = voteSystemName.value
Expand All @@ -28,16 +53,8 @@ watch(
{ immediate: true },
)
const saveReady = computed(
() =>
// Required field exist
gameNameDraft.value
&& voteSystemNameDraft.value
// Has any changes in fields
&& !(gameName.value === gameNameDraft.value && voteSystemName.value === voteSystemNameDraft.value),
)
function save() {
gameName.value = gameNameDraft.value
gameName.value = gameNameDraft.value.trim()
voteSystemName.value = voteSystemNameDraft.value
visible.value = false
Expand All @@ -56,23 +73,58 @@ defineExpose({ toggle })
content: { style: 'padding: unset' },
}"
>
<game-settings
v-model:game-name="gameNameDraft"
v-model:vote-system-name="voteSystemNameDraft"
/>
<div class="settings">
<div class="group">
<span>Game name</span>
<p-input-text
id="game-name"
v-model="gameNameDraft"
:class="{ 'p-invalid': constraint.has('gameName') }"
:maxlength="20"
/>
<small v-if="constraint.has('gameName')" id="game-name-help">{{ constraint.get('gameName') }}</small>
</div>
<div class="group">
<span>Game vote system</span>
<p-dropdown
id="vote-system"
v-model="voteSystemNameDraft"
:options="voteSystemOptions"
:class="{ 'p-invalid': constraint.has('voteSystemName') }"
option-value="name"
option-label="description"
/>
<small v-if="constraint.has('voteSystemName')" id="vote-systemc">{{ constraint.get('voteSystemName') }}</small>
</div>
<div class="group">
<span>Vote system preview</span>
<cards-selector :vote-system-name="voteSystemNameDraft" />
</div>
</div>
<div class="actions">
<p-button
icon="pi pi-save"
label="save"
severity="success"
:disabled="!saveReady"
:disabled="constraint.size > 0"
@click="save"
/>
</div>
</p-dialog>
</template>

<style scoped>
.settings {
display: flex;
flex-direction: column;
gap: calc(var(--content-padding) * 1.5);
padding: var(--content-padding);
}
.group {
display: flex;
flex-direction: column;
gap: var(--inline-spacing);
}
.actions {
display: flex;
align-items: center;
Expand Down
54 changes: 42 additions & 12 deletions src/components/UserSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,56 @@ watch(
() => (usernameDraft.value = username.value),
{ immediate: true },
)
const constraint = computed(() => {
const errors = new Map<'username', string>()
const name = usernameDraft.value?.trim()
if (!name) {
errors.set('username', `Name must be non empty`)
}
else if (name.length < 3) {
errors.set('username', `Name must be at least 3 symbol length`)
}
else if (name.length > 15) {
errors.set('username', `Name must be less 15 symbol length`)
}
return errors
})
watchDebounced(
() => usernameDraft.value,
(name) => {
if (name) {
username.value = name
() => {
const name = usernameDraft.value?.trim()
if (name && constraint.value.size === 0) {
username.value = name.trim()
}
},
{ debounce: 1000 },
)
</script>

<template>
<span class="p-input-icon-right">
<i v-show="usernameDraft !== username" class="pi pi-spin pi-spinner" />
<p-input-text
v-model="usernameDraft"
:class="{ 'p-invalid': !usernameDraft }"
:maxlength="10"
/>
</span>
<div class="username-container">
<span class="usename-input">
<p-input-text
id="username"
v-model="usernameDraft"
:class="{ 'p-invalid': constraint.has('username') }"
:maxlength="20"
/>
<i v-show="usernameDraft !== username && constraint.size === 0" class="pi pi-spin pi-spinner" />
</span>
<small v-if="constraint.has('username')" id="username-help">{{ constraint.get('username') }}</small>
</div>
</template>

<style scoped></style>
<style scoped>
.username-container {
display: flex;
flex-direction: column;
gap: var(--inline-spacing);
}
.usename-input {
display: flex;
align-items: center;
gap: var(--inline-spacing);
}
</style>
1 change: 1 addition & 0 deletions src/composables/useGame.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { object, optional, parse, picklist, string } from 'valibot'
import type { PostgrestError } from '@supabase/supabase-js'
import type { Ref } from 'vue'
import supabase from '@/plugins/supabase'

function throwIfNok(res: string, event: string) {
Expand Down
5 changes: 4 additions & 1 deletion src/views/GameView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ const groupedView = ref(false)
/>
</div>

<p-overlay-panel ref="userSettingsEl">
<p-overlay-panel
ref="userSettingsEl"
:pt="{ content: { style: { padding: 'var(--inline-spacing)' } } }"
>
<user-settings v-model:username="user.name" />
</p-overlay-panel>
<share-dialog ref="shareDialogEl" />
Expand Down

0 comments on commit 28e3d00

Please sign in to comment.