Add Score board page to visualize progress of exercises
This commit is contained in:
@@ -59,6 +59,7 @@ const navRail = defineModel("navRail", { type: Boolean })
|
|||||||
<div v-else></div>
|
<div v-else></div>
|
||||||
</v-list-subheader>
|
</v-list-subheader>
|
||||||
<v-list-item :title="$t('menu.helpInstructions')" prepend-icon="mdi-chat-question" to="/help" link />
|
<v-list-item :title="$t('menu.helpInstructions')" prepend-icon="mdi-chat-question" to="/help" link />
|
||||||
|
<v-list-item :title="$t('menu.scoreBoard')" prepend-icon="mdi-podium-gold" to="/scoreBoard" link />
|
||||||
<v-list-item :title="$t('menu.preferences')" prepend-icon="mdi-cog" to="/preferences" link />
|
<v-list-item :title="$t('menu.preferences')" prepend-icon="mdi-cog" to="/preferences" link />
|
||||||
</v-list>
|
</v-list>
|
||||||
</template>
|
</template>
|
||||||
11
software/src/data/stores/scoreStore.ts
Normal file
11
software/src/data/stores/scoreStore.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { useLocalStorage } from "@vueuse/core";
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
|
const useScoreStore = defineStore("scoreStore", {
|
||||||
|
state: () => ({
|
||||||
|
progressGroup0: useLocalStorage("hackmycart/scoreStore/progressGroup0", 0),
|
||||||
|
progressGroup1: useLocalStorage("hackmycart/scoreStore/progressGroup1", 0),
|
||||||
|
progressGroup2: useLocalStorage("hackmycart/scoreStore/progressGroup2", 0),
|
||||||
|
progressGroup3: useLocalStorage("hackmycart/scoreStore/progressGroup3", 0),
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -9,7 +9,8 @@
|
|||||||
"systemAndHelp": "System & Hilfe",
|
"systemAndHelp": "System & Hilfe",
|
||||||
"helpInstructions": "Hilfestellung",
|
"helpInstructions": "Hilfestellung",
|
||||||
"preferences": "Einstellungen",
|
"preferences": "Einstellungen",
|
||||||
"logout": "Ausloggen"
|
"logout": "Ausloggen",
|
||||||
|
"scoreBoard": "Score Board"
|
||||||
},
|
},
|
||||||
"preferences": {
|
"preferences": {
|
||||||
"pageSetup": "Seiteneinstellungen",
|
"pageSetup": "Seiteneinstellungen",
|
||||||
@@ -102,5 +103,12 @@
|
|||||||
"title": "Datenbank zurücksetzen?",
|
"title": "Datenbank zurücksetzen?",
|
||||||
"description": "Soll die Datenbank des Servers wirklich zurückgesetzt werden? Dies kann nicht rückgänig gemacht werden!"
|
"description": "Soll die Datenbank des Servers wirklich zurückgesetzt werden? Dies kann nicht rückgänig gemacht werden!"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"scoreBoard": {
|
||||||
|
"exerciseGroup0": "Aufgabengruppe 0: Den Shop kennenlernen",
|
||||||
|
"exerciseGroup1": "Aufgabengruppe 1: SQL Injections",
|
||||||
|
"exerciseGroup2": "Aufgabengruppe 2: Broken Access Control",
|
||||||
|
"exerciseGroup3": "Aufgabengruppe 3: Cross-Site Scripting (XSS)",
|
||||||
|
"exercise": "Aufgabe {0}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
"systemAndHelp": "System & Help",
|
"systemAndHelp": "System & Help",
|
||||||
"helpInstructions": "Help instructions",
|
"helpInstructions": "Help instructions",
|
||||||
"preferences": "Preferences",
|
"preferences": "Preferences",
|
||||||
"logout": "Logout"
|
"logout": "Logout",
|
||||||
|
"scoreBoard": "Score Board"
|
||||||
},
|
},
|
||||||
"preferences": {
|
"preferences": {
|
||||||
"pageSetup": "Page setup",
|
"pageSetup": "Page setup",
|
||||||
@@ -102,5 +103,12 @@
|
|||||||
"title": "Reset database?",
|
"title": "Reset database?",
|
||||||
"description": "Do you really want to reset the server database? This can't be undone!"
|
"description": "Do you really want to reset the server database? This can't be undone!"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"scoreBoard": {
|
||||||
|
"exerciseGroup0": "Exercise Group 0: Getting Started",
|
||||||
|
"exerciseGroup1": "Exercise Group 1: SQL Injections",
|
||||||
|
"exerciseGroup2": "Exercise Group 2: Broken Access Control",
|
||||||
|
"exerciseGroup3": "Exercise Group 3: Cross-Site Scripting (XSS)",
|
||||||
|
"exercise": "Exercise {0}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
51
software/src/pages/scoreBoardPage/index.vue
Normal file
51
software/src/pages/scoreBoardPage/index.vue
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import scoreCard from './scoreCard.vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<v-container max-width="1000">
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<score-card
|
||||||
|
:title="$t('scoreBoard.exerciseGroup0')"
|
||||||
|
:progress="2"
|
||||||
|
:total-steps="2"
|
||||||
|
:step-names="['Registrieren', 'Bestellung ausführen']"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<score-card
|
||||||
|
:title="$t('scoreBoard.exerciseGroup1')"
|
||||||
|
:progress="1"
|
||||||
|
:total-steps="4"
|
||||||
|
:step-names="['', '']"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<score-card
|
||||||
|
:title="$t('scoreBoard.exerciseGroup2')"
|
||||||
|
:progress="1"
|
||||||
|
:total-steps="4"
|
||||||
|
:step-names="['', '']"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<score-card
|
||||||
|
:title="$t('scoreBoard.exerciseGroup3')"
|
||||||
|
:progress="0"
|
||||||
|
:total-steps="3"
|
||||||
|
:step-names="['', '', '']"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-container>
|
||||||
|
</template>
|
||||||
49
software/src/pages/scoreBoardPage/scoreCard.vue
Normal file
49
software/src/pages/scoreBoardPage/scoreCard.vue
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import cardView from '@/components/cardView.vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
exerciseGroup: String,
|
||||||
|
progress: Number,
|
||||||
|
totalSteps: Number,
|
||||||
|
stepNames: Array<String>
|
||||||
|
})
|
||||||
|
|
||||||
|
function getDotColor(step: number) {
|
||||||
|
if (props.progress >= step) {
|
||||||
|
return "green"
|
||||||
|
} else {
|
||||||
|
return "grey"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIcon(step: number) {
|
||||||
|
if (props.progress >= step) {
|
||||||
|
return "mdi-check"
|
||||||
|
} else {
|
||||||
|
return "mdi-pencil"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<card-view :title="exerciseGroup" >
|
||||||
|
<v-timeline
|
||||||
|
direction="horizontal"
|
||||||
|
side="end"
|
||||||
|
class="pb-3"
|
||||||
|
>
|
||||||
|
<v-timeline-item
|
||||||
|
v-for="step in totalSteps"
|
||||||
|
:dot-color="getDotColor(step)"
|
||||||
|
:icon="getIcon(step)"
|
||||||
|
>
|
||||||
|
{{ stepNames[step - 1] }}
|
||||||
|
|
||||||
|
<template #opposite>
|
||||||
|
{{ $t('scoreBoard.exercise', [step]) }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</v-timeline-item>
|
||||||
|
</v-timeline>
|
||||||
|
</card-view>
|
||||||
|
</template>
|
||||||
@@ -5,6 +5,7 @@ import ProductsPage from "@/pages/productsPage/index.vue";
|
|||||||
import LoginPage from "@/pages/loginPage/index.vue"
|
import LoginPage from "@/pages/loginPage/index.vue"
|
||||||
import BasketPage from "@/pages/basketPage/index.vue"
|
import BasketPage from "@/pages/basketPage/index.vue"
|
||||||
import HelpPage from "@/pages/helpPage/index.vue"
|
import HelpPage from "@/pages/helpPage/index.vue"
|
||||||
|
import ScoreBoardPage from "@/pages/scoreBoardPage/index.vue"
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{ path: '/', component: ProductsPage },
|
{ path: '/', component: ProductsPage },
|
||||||
@@ -13,6 +14,7 @@ const routes = [
|
|||||||
{ path: '/preferences', component: PreferencesPage },
|
{ path: '/preferences', component: PreferencesPage },
|
||||||
{ path: '/login', component: LoginPage },
|
{ path: '/login', component: LoginPage },
|
||||||
{ path: '/basket', component: BasketPage },
|
{ path: '/basket', component: BasketPage },
|
||||||
|
{ path: '/scoreboard', component: ScoreBoardPage },
|
||||||
{ path: '/help', component: HelpPage }
|
{ path: '/help', component: HelpPage }
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user