puzzle/src/frontend/components/NewGameDialog.vue

196 lines
4.9 KiB
Vue
Raw Normal View History

2021-05-17 00:27:47 +02:00
<template>
2021-05-21 00:43:02 +02:00
<div class="overlay new-game-dialog" @click="$emit('bgclick')">
<div class="overlay-content" @click.stop="">
2021-05-13 14:01:10 +02:00
2021-05-21 00:43:02 +02:00
<div class="area-image">
<div class="has-image">
<responsive-image :src="image.url" :title="image.title" />
</div>
2021-06-05 10:27:50 +02:00
<div class="image-title" v-if="image.title">"{{image.title}}"</div>
2021-05-21 00:43:02 +02:00
</div>
<div class="area-settings">
<table>
<tr>
<td><label>Pieces</label></td>
<td><input type="text" v-model="tiles" /></td>
</tr>
<tr>
<td><label>Scoring: </label></td>
<td>
<label><input type="radio" v-model="scoreMode" value="1" /> Any (Score when pieces are connected to each other or on final location)</label>
<br />
<label><input type="radio" v-model="scoreMode" value="0" /> Final (Score when pieces are put to their final location)</label>
</td>
</tr>
2021-06-03 09:07:57 +02:00
<tr>
2021-06-03 09:32:39 +02:00
<td><label>Shapes: </label></td>
2021-06-03 09:07:57 +02:00
<td>
<label><input type="radio" v-model="shapeMode" value="0" /> Normal</label>
<br />
<label><input type="radio" v-model="shapeMode" value="1" /> Any (flat pieces can occur anywhere)</label>
<br />
<label><input type="radio" v-model="shapeMode" value="2" /> Flat (all pieces flat on all sides)</label>
</td>
</tr>
2021-06-04 09:26:37 +02:00
<tr>
<td><label>Snapping: </label></td>
<td>
<label><input type="radio" v-model="snapMode" value="0" /> Normal (pieces snap to final destination and to each other)</label>
<br />
<label><input type="radio" v-model="snapMode" value="1" /> Real (pieces snap only to corners, already snapped pieces and to each other)</label>
</td>
</tr>
2021-05-21 00:43:02 +02:00
</table>
</div>
<div class="area-buttons">
<button class="btn" :disabled="!canStartNewGame" @click="onNewGameClick">
🧩 Generate Puzzle
</button>
</div>
2021-05-13 14:01:10 +02:00
</div>
2021-05-17 00:27:47 +02:00
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
2021-06-04 09:26:37 +02:00
import { GameSettings, ScoreMode, ShapeMode, SnapMode } from './../../common/Types'
2021-05-21 00:43:02 +02:00
import ResponsiveImage from './ResponsiveImage.vue'
2021-05-17 00:27:47 +02:00
export default defineComponent({
name: 'new-game-dialog',
components: {
2021-05-21 00:43:02 +02:00
ResponsiveImage,
2021-05-17 00:27:47 +02:00
},
2021-05-13 14:01:10 +02:00
props: {
2021-05-21 00:43:02 +02:00
image: {
type: Object,
required: true,
},
2021-05-13 14:01:10 +02:00
},
emits: {
newGame: null,
2021-05-21 00:43:02 +02:00
bgclick: null,
2021-05-13 14:01:10 +02:00
},
data() {
return {
tiles: 1000,
2021-05-17 02:32:33 +02:00
scoreMode: ScoreMode.ANY,
2021-06-03 09:07:57 +02:00
shapeMode: ShapeMode.NORMAL,
2021-06-04 09:26:37 +02:00
snapMode: SnapMode.NORMAL,
2021-05-13 14:01:10 +02:00
}
},
methods: {
2021-05-21 00:43:02 +02:00
onNewGameClick () {
2021-05-13 14:01:10 +02:00
this.$emit('newGame', {
tiles: this.tilesInt,
image: this.image,
scoreMode: this.scoreModeInt,
2021-06-03 09:07:57 +02:00
shapeMode: this.shapeModeInt,
2021-06-04 09:26:37 +02:00
snapMode: this.snapModeInt,
2021-05-21 00:43:02 +02:00
} as GameSettings)
2021-05-13 14:01:10 +02:00
},
},
computed: {
2021-05-21 00:43:02 +02:00
canStartNewGame () {
if (
!this.tilesInt
|| !this.image
|| !this.image.url
|| ![0, 1].includes(this.scoreModeInt)
) {
return false
}
return true
},
2021-05-17 00:27:47 +02:00
scoreModeInt (): number {
return parseInt(`${this.scoreMode}`, 10)
2021-05-13 14:01:10 +02:00
},
2021-06-03 09:07:57 +02:00
shapeModeInt (): number {
return parseInt(`${this.shapeMode}`, 10)
},
2021-06-04 09:26:37 +02:00
snapModeInt (): number {
return parseInt(`${this.snapMode}`, 10)
},
2021-05-17 00:27:47 +02:00
tilesInt (): number {
return parseInt(`${this.tiles}`, 10)
2021-05-13 14:01:10 +02:00
},
},
2021-05-17 00:27:47 +02:00
})
</script>
2021-05-21 00:43:02 +02:00
// TODO: scoped vs .new-game-dialog
<style>
.new-game-dialog .overlay-content {
display: grid;
grid-template-columns: auto 450px;
grid-template-rows: auto;
grid-template-areas:
"image settings"
"image buttons";
height: 90%;
width: 80%;
}
2021-06-05 10:27:50 +02:00
.new-game-dialog .area-image {
grid-area: image;
display: grid;
grid-template-rows: 1fr min-content;
grid-template-areas:
"image"
"image-title";
margin-right: 1em;
}
2021-06-05 09:54:01 +02:00
@media (max-width: 1400px) {
.new-game-dialog .overlay-content {
grid-template-columns: auto;
grid-template-rows: 1fr min-content min-content;
grid-template-areas:
"image"
"settings"
"buttons";
}
2021-06-05 10:27:50 +02:00
.new-game-dialog .area-image {
margin-right: 0;
}
2021-05-21 00:43:02 +02:00
}
.new-game-dialog .area-settings {
grid-area: settings;
}
.new-game-dialog .area-settings table input[type="text"] {
width: 100%;
box-sizing: border-box;
}
.new-game-dialog .area-buttons {
align-self: end;
grid-area: buttons;
}
.new-game-dialog .area-buttons button {
width: 100%;
}
.new-game-dialog .has-image {
2021-06-05 10:27:50 +02:00
box-sizing: border-box;
grid-area: image;
2021-05-21 00:43:02 +02:00
position: relative;
width: 100%;
height: 100%;
2021-06-05 10:27:50 +02:00
border: solid 1px;
2021-05-21 00:43:02 +02:00
}
2021-06-05 10:27:50 +02:00
.new-game-dialog .image-title {
grid-area: image-title;
text-align: center;
padding: .5em 0;
background: var(--main-color);
color: #262523;
}
2021-05-21 00:43:02 +02:00
.new-game-dialog .has-image .remove {
position: absolute;
top: .5em;
left: .5em;
}
</style>