Template
feat : working UI for words
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import { useUserStore } from '~/store/user.store';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<header>
|
||||
<div id="self">
|
||||
<template v-if="userStore.has_contacted">
|
||||
<ClientOnly>
|
||||
<template v-if="userStore.self && userStore.self.id">
|
||||
<User :id="userStore.self.id"></User>
|
||||
<button>Logout</button>
|
||||
</template>
|
||||
<button v-else>Login</button>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
<template v-else>
|
||||
Contacting server...
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div id="links">
|
||||
<NuxtLink to="/">Home</NuxtLink>
|
||||
<NuxtLink to="/words">Words</NuxtLink>
|
||||
</div>
|
||||
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped>
|
||||
header,
|
||||
header * {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
div#self {
|
||||
height: 32px
|
||||
}
|
||||
|
||||
div#links {
|
||||
width: 100%;
|
||||
gap: 1%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,35 @@
|
||||
<script setup lang="ts">
|
||||
import { fetchUser } from '~/service/user.service';
|
||||
import { useUserStore } from '~/store/user.store';
|
||||
|
||||
|
||||
export interface Props {
|
||||
id: string;
|
||||
}
|
||||
|
||||
const userStore = useUserStore();
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const user = await userStore.fetchUser(props.id)
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="user">
|
||||
<img class="user-avatar" :src="`https://cdn.discordapp.com/avatars/${user?.id}/${user?.avatar}.webp?size=32`">
|
||||
{{ user?.username }}
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style lang="css">
|
||||
div.user {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
img.user-avatar {
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,56 @@
|
||||
<script setup lang="ts">
|
||||
import type { WordResponseDTO } from '~/netcode/events/dto/wordresponse.dto';
|
||||
import { useWordStore } from '~/store/word.store';
|
||||
|
||||
export interface Props {
|
||||
word: WordResponseDTO;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const loading = ref(false)
|
||||
const wordStore = useWordStore();
|
||||
|
||||
async function changeWordState() {
|
||||
if (loading.value) {
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
let data
|
||||
if (props.word.enabled) {
|
||||
data = await wordStore.disableWord(props.word.id)
|
||||
} else {
|
||||
data = await wordStore.enableWord(props.word.id)
|
||||
}
|
||||
loading.value = false
|
||||
props.word.enabled = data.enabled
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="word">
|
||||
<span>{{ word.value }}</span>
|
||||
<input type="checkbox" :class="{ loading }" :checked="word.enabled" :disabled="loading"
|
||||
@click.prevent="changeWordState" />
|
||||
<User :id="word.ownerId"></User>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped>
|
||||
div.word {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
input {
|
||||
min-height: 28px;
|
||||
}
|
||||
|
||||
input.loading {
|
||||
cursor: wait
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user