Merge pull request #12 from Kugelschieber/ui

User Interface
This commit is contained in:
Erik Schilling
2020-12-16 18:41:28 +01:00
committed by GitHub
8 changed files with 282 additions and 89 deletions

View File

@@ -1,18 +1,55 @@
<template> <template>
<img alt="Vue logo" src="./assets/logo.png" /> <main>
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App" /> <Level :level="level" />
<Timer :time="time" />
<Buffer :slots="slots" :codes="codes" />
<Matrix :size="size" :matrix="matrix" />
</main>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import {defineComponent} from "vue";
import HelloWorld from './components/HelloWorld.vue'; import Level from "./components/Level.vue";
import Timer from "./components/Timer.vue";
import Buffer from "./components/Buffer.vue";
import Matrix from "./components/Matrix.vue";
export default defineComponent({ export default defineComponent({
name: 'App',
components: { components: {
HelloWorld Level,
Timer,
Buffer,
Matrix
},
setup() {
const time = new Date();
time.setSeconds(time.getSeconds()+60);
return {
level: 5,
time,
slots: ["99", "E7", "AD", ""],
codes: [
{
code: ["", "E7", "AD", "BD"],
points: 100
},
{
code: ["99", "E7", "AD"],
points: 50
} }
}); ],
size: 5,
matrix: [
"99", "E7", "AD", "99", "BD",
"99", "BD", "99", "E7", "AD",
"AD", "E7", "BD", "AD", "99",
"99", "99", "BD", "E7", "AD",
"E7", "AD", "99", "BD", "99"
]
}
}
});
</script> </script>
<style lang="scss"> <style lang="scss">

32
src/components/Buffer.vue Normal file
View File

@@ -0,0 +1,32 @@
<template>
<div class="buffer">
<h2>Buffer</h2>
<div class="buffer-slots">
<div class="buffer-slots-slot buffer-slots-border" v-for="(slot, i) in slots" :key="i">
{{slot}}
</div>
</div>
<h2>Sequences</h2>
<div class="buffer-codes" v-for="(code, i) in codes" :key="i">
<div class="buffer-slots">
<div class="buffer-slots-slot" v-for="(digit, j) in code.code" :key="j">
{{digit}}
</div>
</div>
<div class="buffer-points">
{{code.points}} Pts
</div>
</div>
</div>
</template>
<script lang="ts">
import {defineComponent} from "vue";
export default defineComponent({
props: {
slots: {type: Array, required: true},
codes: {type: Array, required: true}
}
});
</script>

View File

@@ -1,16 +0,0 @@
import "jest";
import {shallowMount} from "@vue/test-utils";
import HelloWorld from "../components/HelloWorld.vue";
describe("HelloWorld.vue", () => {
test("renders props.msg when passed", () => {
const msg = "new message"
const wrapper = shallowMount(HelloWorld, {
propsData: {
msg
}
});
expect(wrapper.text()).toMatch(msg)
});
});

View File

@@ -1,61 +0,0 @@
<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-typescript" target="_blank" rel="noopener">typescript</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 lang="ts">
import {defineComponent} from 'vue';
export default defineComponent({
props: {
msg: String
}
});
</script>
<style lang="scss">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

16
src/components/Level.vue Normal file
View File

@@ -0,0 +1,16 @@
<template>
<div class="level">
<h1>Breach</h1>
<div class="level-display">Level <span>{{level}}</span></div>
</div>
</template>
<script lang="ts">
import {defineComponent} from "vue";
export default defineComponent({
props: {
level: {type: Number, required: true}
}
});
</script>

21
src/components/Matrix.vue Normal file
View File

@@ -0,0 +1,21 @@
<template>
<div class="matrix">
<h2>Code-Matrix</h2>
<div class="matrix-row" v-for="i in size" :key="i">
<div class="matrix-column" v-for="j in size" :key="j">
{{matrix[(i - 1)*5 + (j - 1)]}}
</div>
</div>
</div>
</template>
<script lang="ts">
import {defineComponent} from "vue";
export default defineComponent({
props: {
size: {type: Number, required: true},
matrix: {type: Array, required: true},
}
});
</script>

39
src/components/Timer.vue Normal file
View File

@@ -0,0 +1,39 @@
<template>
<div class="timer">
<div class="timer-countdown">{{countdown}}</div>
<div class="timer-progress" :style="{width: `${progress}%`}"></div>
</div>
</template>
<script lang="ts">
import {defineComponent, ref, computed} from "vue";
export default defineComponent({
props: {
time: {type: Object, required: true}
},
setup(props) {
const remainingTime = ref(60)
const progress = computed(() => remainingTime.value/60*100);
const countdown = computed(() => remainingTime.value.toFixed(2));
const updateTime = () => {
remainingTime.value = Math.max(0, (props.time.getTime() - new Date().getTime()) / 1000);
if (remainingTime.value > 0) {
requestAnimationFrame(() => {
updateTime();
});
}
}
requestAnimationFrame(() => {
updateTime();
});
return {
countdown,
progress
};
}
});
</script>

View File

@@ -1,3 +1,128 @@
body { @import url('https://fonts.googleapis.com/css2?family=Inconsolata&display=swap');
background: rgb(238, 238, 238);
$background: #121018;
$yellow: #d0ee58;
* {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
background: $background;
color: $yellow;
font-family: "Inconsolata", monospace;
font-size: 18px;
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
main {
min-width: 400px;
border: 1px solid $yellow;
padding: 20px;
}
.level {
display: flex;
justify-content: space-between;
align-items: center;
margin: 0 0 10px 0;
&-display {
span {
background: $yellow;
color: $background;
padding: 5px;
font-weight: bold;
}
}
}
.timer {
border: 1px solid $yellow;
margin: 0 0 10px 0;
&-countdown {
padding: 10px;
}
&-progress {
width: 100%;
height: 3px;
background: $yellow;
}
}
.buffer {
border: 1px solid $yellow;
margin: 0 0 10px 0;
padding: 10px;
&-codes {
display: flex;
justify-content: space-between;
align-items: center;
}
&-slots {
display: flex;
margin: 5px 0;
&-slot {
display: flex;
justify-content: center;
align-items: center;
width: 32px;
height: 32px;
margin: 0 5px 0 0;
}
&-points {
display: flex;
justify-content: center;
align-items: center;
width: 64px;
height: 32px;
}
&-border {
border: 1px solid $yellow;
}
}
}
.matrix {
border: 1px solid $yellow;
padding: 10px;
&-row {
display: flex;
}
&-column {
display: flex;
justify-content: center;
align-items: center;
width: 32px;
height: 32px;
margin: 0 5px 5px 0;
}
}
h1, h2 {
display: flex;
align-items: center;
text-transform: uppercase;
font-size: 18px;
font-weight: normal;
margin: 0;
padding: 5px 0;
height: 32px;
} }