20 changed files with 20936 additions and 1 deletions
@ -1,2 +1,24 @@ |
|||||||
# loveLetterFrontend |
# frontend |
||||||
|
|
||||||
|
## Project setup |
||||||
|
``` |
||||||
|
npm install |
||||||
|
``` |
||||||
|
|
||||||
|
### Compiles and hot-reloads for development |
||||||
|
``` |
||||||
|
npm run serve |
||||||
|
``` |
||||||
|
|
||||||
|
### Compiles and minifies for production |
||||||
|
``` |
||||||
|
npm run build |
||||||
|
``` |
||||||
|
|
||||||
|
### Lints and fixes files |
||||||
|
``` |
||||||
|
npm run lint |
||||||
|
``` |
||||||
|
|
||||||
|
### Customize configuration |
||||||
|
See [Configuration Reference](https://cli.vuejs.org/config/). |
||||||
|
|||||||
@ -0,0 +1,5 @@ |
|||||||
|
module.exports = { |
||||||
|
presets: [ |
||||||
|
'@vue/cli-plugin-babel/preset' |
||||||
|
] |
||||||
|
} |
||||||
@ -0,0 +1,19 @@ |
|||||||
|
{ |
||||||
|
"compilerOptions": { |
||||||
|
"target": "es5", |
||||||
|
"module": "esnext", |
||||||
|
"baseUrl": "./", |
||||||
|
"moduleResolution": "node", |
||||||
|
"paths": { |
||||||
|
"@/*": [ |
||||||
|
"src/*" |
||||||
|
] |
||||||
|
}, |
||||||
|
"lib": [ |
||||||
|
"esnext", |
||||||
|
"dom", |
||||||
|
"dom.iterable", |
||||||
|
"scripthost" |
||||||
|
] |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,46 @@ |
|||||||
|
{ |
||||||
|
"name": "frontend", |
||||||
|
"version": "0.1.0", |
||||||
|
"private": true, |
||||||
|
"scripts": { |
||||||
|
"serve": "vue-cli-service serve", |
||||||
|
"build": "vue-cli-service build", |
||||||
|
"lint": "vue-cli-service lint" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
"core-js": "^3.8.3", |
||||||
|
"socket.io": "^4.4.1", |
||||||
|
"socket.io-client": "^4.4.1", |
||||||
|
"vue": "^3.2.13", |
||||||
|
"vue-router": "^4.0.13" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"@babel/core": "^7.12.16", |
||||||
|
"@babel/eslint-parser": "^7.12.16", |
||||||
|
"@vue/cli-plugin-babel": "~5.0.0", |
||||||
|
"@vue/cli-plugin-eslint": "~5.0.0", |
||||||
|
"@vue/cli-service": "~5.0.0", |
||||||
|
"eslint": "^7.32.0", |
||||||
|
"eslint-plugin-vue": "^8.0.3" |
||||||
|
}, |
||||||
|
"eslintConfig": { |
||||||
|
"root": true, |
||||||
|
"env": { |
||||||
|
"node": true |
||||||
|
}, |
||||||
|
"extends": [ |
||||||
|
"plugin:vue/vue3-essential", |
||||||
|
"eslint:recommended" |
||||||
|
], |
||||||
|
"parserOptions": { |
||||||
|
"parser": "@babel/eslint-parser" |
||||||
|
}, |
||||||
|
"rules": {} |
||||||
|
}, |
||||||
|
"browserslist": [ |
||||||
|
"> 1%", |
||||||
|
"last 2 versions", |
||||||
|
"not dead", |
||||||
|
"not ie 11" |
||||||
|
] |
||||||
|
} |
||||||
|
After Width: | Height: | Size: 4.2 KiB |
@ -0,0 +1,20 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang=""> |
||||||
|
<head> |
||||||
|
<meta charset="utf-8"> |
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0"> |
||||||
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> |
||||||
|
<!-- <link rel="stylesheet" href="https://unpkg.com/primitive-ui/dist/css/main.css" /> --> |
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"> |
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script> |
||||||
|
<title><%= htmlWebpackPlugin.options.title %></title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<noscript> |
||||||
|
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> |
||||||
|
</noscript> |
||||||
|
<div id="app"></div> |
||||||
|
<!-- built files will be auto injected --> |
||||||
|
</body> |
||||||
|
</html> |
||||||
@ -0,0 +1,12 @@ |
|||||||
|
VUEjs with socket.io |
||||||
|
https://www.digitalocean.com/community/tutorials/vuejs-vue-socketio |
||||||
|
|
||||||
|
Setting Vue to run over https |
||||||
|
https://stackoverflow.com/questions/45807049/how-to-run-vue-js-dev-serve-with-https |
||||||
|
|
||||||
|
Using socket.io with vue |
||||||
|
https://lukashermann.dev/writing/socketio-with-vue-and-vuex/ |
||||||
|
|
||||||
|
#Guide to do multiplayer game with Vue and Socket.io |
||||||
|
https://blog.logrocket.com/how-to-create-a-2d-multiplayer-game-with-vue-js-and-socket-io-174ef2818e65/ |
||||||
|
|
||||||
@ -0,0 +1,48 @@ |
|||||||
|
<template> |
||||||
|
<div id="app"> |
||||||
|
<game-lobby v-bind:players="players"/> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import io from "socket.io-client" |
||||||
|
import GameLobby from '@/components/GameLobby.vue' |
||||||
|
import { socketUrl } from './config/appConfig' |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'app', |
||||||
|
components: { |
||||||
|
GameLobby |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
socket: {}, |
||||||
|
players: [] |
||||||
|
} |
||||||
|
}, |
||||||
|
created() { |
||||||
|
// this.socket = io("wss://localhost:9000") |
||||||
|
// this.socket = io("https://localhost:9000") |
||||||
|
// this.socket = io("https://192.168.50.149:9000") |
||||||
|
// this.socket = io("wss://192.168.50.149:9000") |
||||||
|
this.socket = io(socketUrl) |
||||||
|
}, |
||||||
|
mounted () { |
||||||
|
this.socket.on("connect", () => { |
||||||
|
console.log(`app.socket.id: ${this.socket.id}`) |
||||||
|
}) |
||||||
|
this.socket.on("msg", (data) => { |
||||||
|
console.log(data) |
||||||
|
}) |
||||||
|
this.socket.on('playersUpdate', (data) => { |
||||||
|
// console.log(`playersUpdate:`) |
||||||
|
let playersUpdate = data |
||||||
|
// console.log(playersUpdate) |
||||||
|
this.players = playersUpdate |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style> |
||||||
|
</style> |
||||||
|
After Width: | Height: | Size: 6.7 KiB |
@ -0,0 +1,80 @@ |
|||||||
|
<template> |
||||||
|
<div id="game-lobby"> |
||||||
|
<p>Love Letter</p> |
||||||
|
<form> |
||||||
|
<label>pick a username</label> |
||||||
|
<input type="text"> |
||||||
|
</form> |
||||||
|
<table-selection v-bind:tables="tables" /> |
||||||
|
<players-list v-bind:players="players"/> |
||||||
|
<lobby-admin v-if="showLobbyAdmin" /> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import TableSelection from '@/components/TableSelection.vue' |
||||||
|
import LobbyAdmin from '@/components/LobbyAdmin.vue' |
||||||
|
import PlayersList from '@/components/PlayersList.vue' |
||||||
|
export default { |
||||||
|
name: 'game-lobby', |
||||||
|
components: { |
||||||
|
TableSelection, |
||||||
|
PlayersList, |
||||||
|
LobbyAdmin, |
||||||
|
}, |
||||||
|
data () { |
||||||
|
return { |
||||||
|
showLobbyAdmin: true, |
||||||
|
tables: [ |
||||||
|
{ |
||||||
|
number: 1, |
||||||
|
playerCount: "3/4", |
||||||
|
playerListString: "Bob, Joe, Fred", |
||||||
|
inviteCode: "http://banana.com", |
||||||
|
gameId: "AAAAA11111" |
||||||
|
}, |
||||||
|
{ |
||||||
|
number: 2, |
||||||
|
playerCount: "3/4", |
||||||
|
playerListString: "Jon, Jim, Bill", |
||||||
|
inviteCode: "http://banana.com", |
||||||
|
gameId: "BBBBB22222" |
||||||
|
}, |
||||||
|
{ |
||||||
|
number: 3, |
||||||
|
playerCount: "1/4", |
||||||
|
playerListString: "Tim", |
||||||
|
inviteCode: "http://banana.com", |
||||||
|
gameId: "CCCCC33333" |
||||||
|
} |
||||||
|
], |
||||||
|
// players: [ |
||||||
|
// { |
||||||
|
// id: 1, |
||||||
|
// username: 'username1' |
||||||
|
// }, |
||||||
|
// { |
||||||
|
// id: 2, |
||||||
|
// username: 'username2' |
||||||
|
// } |
||||||
|
// ] |
||||||
|
} |
||||||
|
}, |
||||||
|
methods: {}, |
||||||
|
computed: {}, |
||||||
|
props: { |
||||||
|
players: Array |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
#game-lobby { |
||||||
|
background-color: rgb(255, 203, 92); |
||||||
|
width: 100vw; |
||||||
|
height: 100vh; |
||||||
|
} |
||||||
|
.input { |
||||||
|
background: white; |
||||||
|
} |
||||||
|
</style> |
||||||
@ -0,0 +1,45 @@ |
|||||||
|
<template> |
||||||
|
<div id="employee-form"> |
||||||
|
<form @submit.prevent="handleSubmit"> |
||||||
|
<label>Employee name</label> |
||||||
|
<input v-model="employee.name" type="text" /> |
||||||
|
<label>Employee email</label> |
||||||
|
<input v-model="employee.email" type="text" /> |
||||||
|
<button>Add Employee</button> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'employee-form', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
employee: { |
||||||
|
name: '', |
||||||
|
email: '' |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
handleSubmit() { |
||||||
|
console.log('testing handleSubmit') |
||||||
|
this.$emit('add:employee', this.employee) |
||||||
|
} |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
invalidName() { |
||||||
|
return this.employee.name === '' |
||||||
|
}, |
||||||
|
invalidEmail() { |
||||||
|
return this.employee.email === '' |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
form { |
||||||
|
margin-bottom: 2rem; |
||||||
|
} |
||||||
|
</style> |
||||||
@ -0,0 +1,29 @@ |
|||||||
|
<template> |
||||||
|
<div id="employee-table"> |
||||||
|
<table> |
||||||
|
<thead> |
||||||
|
<tr> |
||||||
|
<th>Employee name</th> |
||||||
|
<th>Employee email</th> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody> |
||||||
|
<tr v-for="employee in employees" :key="employee.id"> |
||||||
|
<td>{{ employee.name }}</td> |
||||||
|
<td>{{ employee.email }}</td> |
||||||
|
</tr> |
||||||
|
</tbody> |
||||||
|
</table> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'employee-table', |
||||||
|
props: { |
||||||
|
employees: Array |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped></style> |
||||||
@ -0,0 +1,58 @@ |
|||||||
|
<template> |
||||||
|
<div class="hello"> |
||||||
|
<h1>{{ msg }}</h1> |
||||||
|
<p> |
||||||
|
For a guide and recipes on how to configure / customize this project,<br> |
||||||
|
check out the |
||||||
|
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>. |
||||||
|
</p> |
||||||
|
<h3>Installed CLI Plugins</h3> |
||||||
|
<ul> |
||||||
|
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li> |
||||||
|
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li> |
||||||
|
</ul> |
||||||
|
<h3>Essential Links</h3> |
||||||
|
<ul> |
||||||
|
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li> |
||||||
|
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li> |
||||||
|
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li> |
||||||
|
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li> |
||||||
|
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li> |
||||||
|
</ul> |
||||||
|
<h3>Ecosystem</h3> |
||||||
|
<ul> |
||||||
|
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li> |
||||||
|
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li> |
||||||
|
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li> |
||||||
|
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li> |
||||||
|
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'HelloWorld', |
||||||
|
props: { |
||||||
|
msg: String |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only --> |
||||||
|
<style scoped> |
||||||
|
h3 { |
||||||
|
margin: 40px 0 0; |
||||||
|
} |
||||||
|
ul { |
||||||
|
list-style-type: none; |
||||||
|
padding: 0; |
||||||
|
} |
||||||
|
li { |
||||||
|
display: inline-block; |
||||||
|
margin: 0 10px; |
||||||
|
} |
||||||
|
a { |
||||||
|
color: #42b983; |
||||||
|
} |
||||||
|
</style> |
||||||
@ -0,0 +1,25 @@ |
|||||||
|
<template> |
||||||
|
<div id="lobby-admin"> |
||||||
|
<table> |
||||||
|
|
||||||
|
</table> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'lobby-admin', |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
#lobby-admin { |
||||||
|
border: 4px solid rgb(0, 255, 221); |
||||||
|
height: 300px; |
||||||
|
width: 100vw; |
||||||
|
background-color: black; |
||||||
|
color: white; |
||||||
|
position: absolute; |
||||||
|
bottom: 0; |
||||||
|
} |
||||||
|
</style> |
||||||
@ -0,0 +1,34 @@ |
|||||||
|
<template> |
||||||
|
<div id="players-List"> |
||||||
|
<p>Love Letter</p> |
||||||
|
<table> |
||||||
|
<thead> |
||||||
|
<tr> |
||||||
|
<th>Online Players</th> |
||||||
|
<th>Connected</th> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody> |
||||||
|
<tr v-for="player in players" :key="player.id"> |
||||||
|
<td>{{ player.username }}</td> |
||||||
|
<td>{{ player.connected }}</td> |
||||||
|
</tr> |
||||||
|
</tbody> |
||||||
|
</table> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'players-List', |
||||||
|
props: { |
||||||
|
players: Array |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
table, th, td { |
||||||
|
border: 1px solid black; |
||||||
|
} |
||||||
|
</style> |
||||||
@ -0,0 +1,41 @@ |
|||||||
|
<template> |
||||||
|
<div id="table-selection"> |
||||||
|
<table> |
||||||
|
<thead> |
||||||
|
<tr> |
||||||
|
<th>#</th> |
||||||
|
<th>playerCount</th> |
||||||
|
<th>players</th> |
||||||
|
<th>inviteCode</th> |
||||||
|
<th>gameId</th> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody> |
||||||
|
<tr v-for="table in tables" :key="table.number"> |
||||||
|
<td>{{ table.number }}</td> |
||||||
|
<td>{{ table.playerCount }}</td> |
||||||
|
<td>{{ table.playerListString }}</td> |
||||||
|
<td>{{ table.inviteCode }}</td> |
||||||
|
<td>{{ table.gameId }}</td> |
||||||
|
</tr> |
||||||
|
</tbody> |
||||||
|
</table> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'table-selection', |
||||||
|
props: { |
||||||
|
tables: Array |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
table, th, td { |
||||||
|
border: 1px solid black; |
||||||
|
background-color: gray; |
||||||
|
color: white; |
||||||
|
} |
||||||
|
</style> |
||||||
@ -0,0 +1,4 @@ |
|||||||
|
const socketUrl = "wss://localhost:9000" |
||||||
|
module.exports = { |
||||||
|
socketUrl: socketUrl |
||||||
|
} |
||||||
@ -0,0 +1,9 @@ |
|||||||
|
// main.js
|
||||||
|
import { createApp } from 'vue' |
||||||
|
import App from './App.vue' |
||||||
|
|
||||||
|
createApp(App).mount('#app') |
||||||
|
|
||||||
|
// socketio
|
||||||
|
// import socket from './socket'
|
||||||
|
// App.prototype.$socket = socket
|
||||||
Loading…
Reference in new issue