initial commit

This commit is contained in:
Jose Conde
2024-06-29 16:40:11 +02:00
commit 2ac728fe02
108 changed files with 7630 additions and 0 deletions

15
src/views/AboutView.vue Normal file
View File

@ -0,0 +1,15 @@
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<style>
@media (min-width: 1024px) {
.about {
min-height: 100vh;
display: flex;
align-items: center;
}
}
</style>

301
src/views/GameView.vue Normal file
View File

@ -0,0 +1,301 @@
<script setup lang="ts">
import GameComponent from '@/components/GameComponent.vue'
import TileComponent from '@/components/TileComponent.vue'
import type { GameState, PlayerState } from '@/utilities/interfaces'
import { inject, onBeforeUnmount, ref } from 'vue'
import { onMounted } from 'vue'
const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
const socketService: any = inject('socket')
const { socket } = socketService
let gameState = ref<GameState | undefined>(undefined)
let playerState = ref<PlayerState | undefined>(undefined)
let data = ref('')
let responseField = ref('')
let statusField = ref('')
let sessionId = ref('')
let selectdAction: any = undefined
let canSelectTile = false
let canMakeMove = false
let tileSelected = ''
let moveType = ''
const options = [
{ value: 'createSession', default: '{"user": "arhuako"}' },
{ value: 'startSession', default: (id: string) => `{"sessionId": "${id}"}` },
{ value: 'joinSession', default: '{"user": "pepe", "sessionId": "arhuako"}' },
{ value: 'leaveSession', default: '{"user": "pepe", "sessionId": "arhuako"}' },
{ value: 'chat message', default: 'chat message' }
]
onMounted(async () => {
socket.on('gameState', (data: GameState, callback: any) => {
gameState.value = data
statusField.value = statusField.value + JSON.stringify(data, null, 2)
callback({
status: 'ok'
})
})
socket.on('playerState', (data: PlayerState, callback: any) => {
console.log('playerState :>> ', data)
playerState.value = data
statusField.value = statusField.value + JSON.stringify(data, null, 2)
callback({
status: 'ok'
})
})
socket.on('makeMove', async (data: any, callback: any) => {
statusField.value = statusField.value + JSON.stringify(data, null, 2)
canMakeMove = true
while (canMakeMove) {
await wait(500)
}
callback({
status: 'ok',
tileId: tileSelected,
moveType
})
})
socket.on('chooseTile', async (data: any, callback: any) => {
statusField.value = statusField.value + JSON.stringify(data, null, 2)
canSelectTile = true
while (canSelectTile) {
await wait(500)
}
callback({
status: 'ok',
tileId: tileSelected
})
})
})
function selectTile(id: string) {
if (canSelectTile) {
tileSelected = id
canSelectTile = false
}
}
function selectTileToMove(id: string) {
if (canMakeMove) {
if (tileSelected === id) {
tileSelected = ''
return
}
tileSelected = id
}
}
function onTileClick(tileId: string) {
console.log('tileId :>> ', tileId)
selectTile(tileId)
}
function makeMove(type: string) {
if (canMakeMove) {
if (type === 'pass') {
tileSelected = ''
canMakeMove = false
} else if (tileSelected) {
moveType = type
canMakeMove = false
}
}
}
onBeforeUnmount(() => {
socketService.disconnect()
})
function actionSelected() {
console.log('event :>> ', selectdAction)
if (selectdAction.value === 'createSession') {
responseField.value = ''
} else if (selectdAction.value === 'startSession') {
data.value = selectdAction.default(sessionId.value)
return
}
data.value = selectdAction.default
}
const getMessage = (msg: string) => {
if (msg.startsWith('{') && msg.endsWith('}')) return JSON.parse(msg)
return msg
}
async function sendMessage() {
if (selectdAction && data.value.trim() !== '') {
console.log('socketService :>> ', socketService)
const response = await socketService.sendMessageWithAck(
selectdAction.value,
getMessage(data.value.trim())
)
console.log('response :>> ', response)
handleResponse(response)
}
// socketService.emit('message', data.value)
}
function handleResponse(response: any) {
if (selectdAction.value === 'createSession') {
sessionId.value = response.sessionId
}
data.value = ''
const responseStr = JSON.stringify(response, null, 2)
responseField.value = !responseField.value
? responseStr
: responseField.value + '\n---\n ' + responseStr
selectdAction = undefined
}
</script>
<template>
<div class="grid">
<div>
<GameComponent :gameState="gameState" :playerState="playerState" @tileClick="onTileClick" />
<p>SessionID: {{ sessionId }}</p>
<ul id="messages"></ul>
<form id="form" action="">
<p>
<select v-model="selectdAction" id="event" autocomplete="off" @change="actionSelected">
<option value="">Select event</option>
<option :key="option.value" v-for="option in options" :value="option">
{{ option.value }}
</option>
</select>
</p>
<!-- <p><input id="room" autocomplete="off" /></p> -->
<p>
<textarea v-model="data" id="message" autocomplete="off" placeholder="Data"></textarea>
</p>
<p><button @click.prevent.stop="sendMessage">Send</button></p>
<div class="grid">
<div>
<textarea
:value="responseField"
id="response"
autocomplete="off"
placeholder="Response"
></textarea>
</div>
<div>
<textarea
:value="statusField"
id="status"
autocomplete="off"
placeholder="Game status"
></textarea>
</div>
</div>
</form>
</div>
<div>
<!-- <div style="display: flex; gap: 4px">
<TileComponent :revealed="false" :top="6" :bottom="0" />
<TileComponent :revealed="true" :top="6" :bottom="0" />
</div> -->
<h4>Board</h4>
<!-- Board -->
<div class="board-container">
<div v-if="gameState?.tileSelectionPhase">
<div class="tiles-container">
<TileComponent
:key="tile.id"
v-for="tile in gameState.boneyard"
@tile-clicked="selectTile(tile.id)"
/>
</div>
<div v-if="canSelectTile">Please select a tile.</div>
<div v-else>Wait your turn.</div>
</div>
<div v-if="!gameState?.tileSelectionPhase">
<div class="tiles-container">
<TileComponent
:class="{ 'selected-tile': tileSelected === tile.id }"
:revealed="true"
:key="tile.id"
v-for="tile in gameState?.board"
:top="tile.pips[0]"
:bottom="tile.pips[1]"
/>
</div>
</div>
</div>
<!-- End board-->
<div class="hand-container">
<h4>
Your Hand <button class="control" @click="makeMove('left')">Left</button
><button class="control" @click="makeMove('right')">Right</button
><button class="control" @click="makeMove('pass')">Pass</button>
</h4>
<div class="tiles-container">
<TileComponent
:revealed="true"
:key="tile.id"
v-for="tile in playerState?.hand ?? []"
@tile-clicked="selectTileToMove(tile.id)"
:top="tile.pips[0]"
:bottom="tile.pips[1]"
/>
</div>
</div>
<!-- End hand-->
</div>
</div>
</template>
<style scoped lang="scss">
* {
box-sizing: border-box;
}
.control {
font-size: 60%;
padding: 8px;
margin-right: 4px;
}
textarea {
width: 100%;
height: 150px;
resize: none;
font-size: 70%;
}
#response,
#status {
height: 400px;
}
.tiles-container {
display: flex;
gap: 4px;
flex-flow: row wrap;
align-content: flex-start;
}
.board-container {
position: absolute;
height: 600px;
padding: 10px;
width: calc(50% - 50px);
background-color: var(--pico-form-element-background-color);
}
.hand-container {
position: fixed;
bottom: 0;
height: 200px;
padding: 10px;
width: calc(50% - 50px);
background-color: var(--pico-form-element-background-color);
}
</style>

24
src/views/HomeView.vue Normal file
View File

@ -0,0 +1,24 @@
<script setup lang="ts">
import { useRouter } from 'vue-router'
const router = useRouter()
function startGame() {
router.push({ name: 'game' })
}
</script>
<template>
<div class="home">
<h1>Welcome to the Player's Home Page</h1>
<p>This is a protected route.</p>
<button @click="startGame">Start Game</button>
</div>
</template>
<style scoped lang="scss">
.home {
max-width: 600px;
margin: auto;
}
</style>

28
src/views/LandingView.vue Normal file
View File

@ -0,0 +1,28 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const username = ref('')
const password = ref('')
function login() {
// if (username.value === 'admin' && password.value === 'password') {
localStorage.setItem('token', 'true')
router.push({ name: 'home' })
// } else {
// alert('Invalid username or password')
// }
}
</script>
<template>
<div class="login">
<h1>Login</h1>
<form @submit.prevent="login">
<input type="text" v-model="username" placeholder="Username" />
<input type="password" v-model="password" placeholder="Password" />
<button type="submit">Login</button>
</form>
</div>
</template>

0
src/views/LoginView.vue Normal file
View File