forked from noxious/client
272 lines
6.9 KiB
Vue
272 lines
6.9 KiB
Vue
<template>
|
|
<div class="character-select-screen">
|
|
<div class="ui-wrapper">
|
|
<div class="characters-wrapper">
|
|
<div v-for="character in characters" :key="character.id" class="character" :class="{ active: selected_character == character.id }">
|
|
<input type="radio" :id="character.id" name="character" :value="character.id" v-model="selected_character" />
|
|
<label :for="character.id">{{ character.name }}</label>
|
|
<!-- @TODO : Add a confirmation dialog -->
|
|
<button class="delete" @click="delete_character(character.id)">
|
|
<img src="/assets/icons/trashcan.svg">
|
|
</button>
|
|
|
|
<div class="sprite-container">
|
|
<img src="/assets/avatar/default/base_right_down.png" />
|
|
</div>
|
|
<span>Lvl. {{ character.level }}</span>
|
|
</div>
|
|
|
|
<div class="character new-character">
|
|
<button @click="isModalOpen = true">
|
|
<img src="/assets/icons/plus-icon.svg" />
|
|
<span>Create new</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="buttons-wrapper">
|
|
<button v-if="selected_character" @click="select_character()">Play</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<Modal :isModalOpen="isModalOpen" @modal:close="isModalOpen = false">
|
|
<template #modal-header>
|
|
<h2 class="modal-title">Create your character</h2>
|
|
</template>
|
|
|
|
<template #modal-body>
|
|
<form method="post" @submit.prevent="create" class="modal-form">
|
|
<div class="form-fields">
|
|
<label for="name">Name</label>
|
|
<input v-model="name" name="name" id="name" />
|
|
</div>
|
|
<div class="submit">
|
|
<button type="submit">Create</button>
|
|
</div>
|
|
</form>
|
|
<button @click="isModalOpen = false">Cancel</button>
|
|
</template>
|
|
</Modal>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { useSocketStore } from '@/stores/socket'
|
|
import { ref } from 'vue'
|
|
import Modal from '@/components/utilities/Modal.vue'
|
|
import {type Character as CharacterT} from '@/types'
|
|
|
|
const socket = useSocketStore()
|
|
|
|
// Fetch characters
|
|
socket.getConnection.on('character:list', (data: any) => {
|
|
characters.value = data
|
|
})
|
|
socket.getConnection.emit('character:list')
|
|
|
|
// Select character logics
|
|
const characters = ref([])
|
|
const selected_character = ref(null)
|
|
function select_character() {
|
|
console.log(selected_character.value)
|
|
if (!selected_character.value) return
|
|
socket.getConnection.emit('character:connect', { character_id: selected_character.value })
|
|
socket.getConnection.on('character:connect', (data: CharacterT) => socket.setCharacter(data))
|
|
}
|
|
|
|
// Delete character logics
|
|
function delete_character(character_id: number) {
|
|
if (!character_id) return
|
|
socket.getConnection.emit('character:delete', { character_id: character_id })
|
|
}
|
|
|
|
// Create character logics
|
|
const isModalOpen = ref(false)
|
|
let name: any = ref('')
|
|
function create() {
|
|
socket.getConnection().on('character:create:success', (data: CharacterT) => {
|
|
socket.setCharacter(data)
|
|
isModalOpen.value = false
|
|
})
|
|
socket.getConnection.emit('character:create', { name: name.value })
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
@import '@/assets/scss/main';
|
|
|
|
.character-select-screen {
|
|
background-image: url('/assets/bglogin.png');
|
|
.ui-wrapper {
|
|
// vertical and vertical center
|
|
height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: center;
|
|
gap: 6.25rem;
|
|
padding: 0 5rem;
|
|
&::before {
|
|
content: '';
|
|
}
|
|
|
|
.characters-wrapper {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 5rem;
|
|
width: 100%;
|
|
|
|
.character {
|
|
width: 150px;
|
|
height: 250px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background-color: rgba($white, 0.8);
|
|
outline: 1px solid $white;
|
|
border-radius: 20px;
|
|
position: relative;
|
|
|
|
&.active {
|
|
background: rgba($light-gray, 0.8);
|
|
}
|
|
|
|
&.new-character {
|
|
background-color: rgba($light-gray, 0.5);
|
|
button {
|
|
background-color: transparent;
|
|
border: none;
|
|
height: 100%;
|
|
width: 100%;
|
|
padding: 40px 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
text-align: center;
|
|
&::before {
|
|
content: '';
|
|
}
|
|
img {
|
|
width: 100px;
|
|
height: 100px;
|
|
margin: auto;
|
|
}
|
|
span {
|
|
align-self: center;
|
|
color: $white;
|
|
font-size: 16px;
|
|
}
|
|
}
|
|
&::before,
|
|
&::after {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
&::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
width: 100%;
|
|
height: 40px;
|
|
background-color: rgba($purple, 0.6);
|
|
border-radius: 20px 20px 0 0;
|
|
}
|
|
|
|
&::after {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: 0;
|
|
width: 100%;
|
|
height: 40px;
|
|
background-color: rgba($purple, 0.6);
|
|
border-radius: 0 0 20px 20px;
|
|
}
|
|
|
|
// hide the radio buttons
|
|
input[type='radio'] {
|
|
opacity: 0;
|
|
height: 100%;
|
|
width: 100%;
|
|
position: absolute;
|
|
}
|
|
|
|
label {
|
|
color: $white;
|
|
font-weight: bold;
|
|
position: absolute;
|
|
top: 20px;
|
|
width: 100%;
|
|
transform: translateY(-50%);
|
|
text-align: center;
|
|
}
|
|
|
|
button.delete {
|
|
background-color: $red;
|
|
border: none;
|
|
width: 30px;
|
|
height: 30px;
|
|
padding: 5px;
|
|
border-radius: 100%;
|
|
z-index: 1;
|
|
right: -10px;
|
|
top: 0;
|
|
transform: translateY(-50%);
|
|
position: absolute;
|
|
|
|
&:hover {
|
|
background-color: $dark-red;
|
|
}
|
|
}
|
|
|
|
span {
|
|
position: absolute;
|
|
bottom: 20px;
|
|
width: 100%;
|
|
text-align: center;
|
|
transform: translateY(50%);
|
|
color: $white;
|
|
z-index: 1;
|
|
}
|
|
|
|
// img under the label
|
|
.sprite-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
margin: auto;
|
|
}
|
|
}
|
|
}
|
|
|
|
.buttons-wrapper {
|
|
display: flex;
|
|
gap: 30px;
|
|
button {
|
|
padding: 10px 16px;
|
|
min-width: 6.25rem;
|
|
text-align: center;
|
|
position: relative;
|
|
background-color: rgba($purple, 0.75);
|
|
border: rgba($white, 0.35) 1px solid;
|
|
border-radius: 5px;
|
|
color: $white;
|
|
font-size: 18px;
|
|
|
|
span {
|
|
color: $white;
|
|
margin: auto;
|
|
}
|
|
|
|
&:hover {
|
|
background-color: rgba($lilac, 0.75);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.modal-title {
|
|
margin: 0;
|
|
}
|
|
}
|
|
</style>
|