Improve UI for smaller screens
This commit is contained in:
@@ -8,19 +8,13 @@ export const exercises = Router()
|
|||||||
* Get all Exercises grouped in ExerciseGroups
|
* Get all Exercises grouped in ExerciseGroups
|
||||||
*/
|
*/
|
||||||
exercises.get("/", (req: Request, res: Response) => {
|
exercises.get("/", (req: Request, res: Response) => {
|
||||||
ExerciseGroup.findAll(
|
Exercise.findAll({
|
||||||
{
|
include: [ ExerciseGroup ]
|
||||||
include: [
|
}).then(result => {
|
||||||
{
|
result.sort((a, b) => {
|
||||||
model: Exercise,
|
return (a.dataValues.exerciseGroup.dataValues.groupNr * 10 + a.dataValues.exerciseNr) > (b.dataValues.exerciseGroup.dataValues.groupNr * 10 + b.dataValues.exerciseNr) ? 1 : -1
|
||||||
separate: true,
|
})
|
||||||
order: [
|
|
||||||
[ 'id', 'ASC' ]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
).then(result => {
|
|
||||||
res.status(200).json(result)
|
res.status(200).json(result)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ function createWindow() {
|
|||||||
const win = new BrowserWindow({
|
const win = new BrowserWindow({
|
||||||
width: 1400,
|
width: 1400,
|
||||||
height: 800,
|
height: 800,
|
||||||
|
minWidth: 800,
|
||||||
|
minHeigth: 600,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
preload: path.join(__dirname, "preload.js"),
|
preload: path.join(__dirname, "preload.js"),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { useFeedbackStore } from './stores/feedback.store';
|
|||||||
import companyFooter from './components/navigation/companyFooter.vue';
|
import companyFooter from './components/navigation/companyFooter.vue';
|
||||||
import urlBar from './components/navigation/urlBar.vue';
|
import urlBar from './components/navigation/urlBar.vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
import NavigationBar from './components/navigation/navigationBar.vue';
|
||||||
|
|
||||||
const preferencesStore = usePreferencesStore()
|
const preferencesStore = usePreferencesStore()
|
||||||
const feedbackStore = useFeedbackStore()
|
const feedbackStore = useFeedbackStore()
|
||||||
@@ -43,20 +44,7 @@ watch(() => feedbackStore.notFound, () => {
|
|||||||
<url-bar />
|
<url-bar />
|
||||||
|
|
||||||
<!-- Navigaion bar of page -->
|
<!-- Navigaion bar of page -->
|
||||||
<v-app-bar
|
<navigation-bar />
|
||||||
height="80"
|
|
||||||
color="primary"
|
|
||||||
class="px-5"
|
|
||||||
elevation="0"
|
|
||||||
>
|
|
||||||
<template #prepend>
|
|
||||||
<navigation-prepend-items />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #append>
|
|
||||||
<navigation-append-items />
|
|
||||||
</template>
|
|
||||||
</v-app-bar>
|
|
||||||
|
|
||||||
|
|
||||||
<v-main>
|
<v-main>
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ defineProps({
|
|||||||
tonal: {
|
tonal: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: "primary"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@@ -20,15 +24,18 @@ defineProps({
|
|||||||
<v-card
|
<v-card
|
||||||
:variant="tonal ? 'tonal' : 'elevated'"
|
:variant="tonal ? 'tonal' : 'elevated'"
|
||||||
>
|
>
|
||||||
<v-card-title v-if="title || loading" color="primary" class="pa-0">
|
<v-card-title
|
||||||
<v-sheet color="primary">
|
v-if="title || loading"
|
||||||
|
class="pa-0"
|
||||||
|
>
|
||||||
|
<v-sheet :color="color">
|
||||||
<v-skeleton-loader
|
<v-skeleton-loader
|
||||||
type="heading"
|
type="heading"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
style="background-color: transparent"
|
style="background-color: transparent"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div class="pl-2 py-1 d-flex justify-center">
|
<div class="px-2 py-1 d-flex justify-center">
|
||||||
<v-icon :icon="icon" v-if="icon" /> {{ title }}
|
<v-icon :icon="icon" v-if="icon" /> {{ title }}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ defineProps({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-row class="pt-3">
|
<v-row class="pt-3 d-none d-md-flex">
|
||||||
<v-col class="d-flex justify-center align-center">
|
<v-col class="d-flex justify-center align-center">
|
||||||
<v-sheet height="12" width="100%" color="primary" class="rounded-s-lg" />
|
<v-sheet height="12" width="100%" color="primary" class="rounded-s-lg" />
|
||||||
</v-col>
|
</v-col>
|
||||||
@@ -26,4 +26,22 @@ defineProps({
|
|||||||
<v-sheet height="12" width="100%" color="primary" class="rounded-e-lg" />
|
<v-sheet height="12" width="100%" color="primary" class="rounded-e-lg" />
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
|
<v-row class="d-md-none">
|
||||||
|
<v-col>
|
||||||
|
<v-skeleton-loader
|
||||||
|
type="heading"
|
||||||
|
:loading="loading"
|
||||||
|
class="d-flex justify-center align-center"
|
||||||
|
>
|
||||||
|
<span class="text-h4 text-center">{{ title }}</span>
|
||||||
|
</v-skeleton-loader>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<v-row class="d-md-none">
|
||||||
|
<v-col class="d-flex justify-center align-center">
|
||||||
|
<v-sheet height="12" width="80%" color="primary" class="rounded-pill" />
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
</template>
|
</template>
|
||||||
@@ -24,17 +24,17 @@ watch(() => route.path, () => {
|
|||||||
inset
|
inset
|
||||||
app
|
app
|
||||||
>
|
>
|
||||||
<v-container class="pa-0 ma-0">
|
<v-container>
|
||||||
<v-row class="mb-0 pa-0">
|
<!-- Current location -->
|
||||||
<v-spacer />
|
<v-row class="w-100">
|
||||||
|
<v-col class="d-flex justify-center">
|
||||||
<v-col>
|
<v-breadcrumbs
|
||||||
<!-- todo: Make more beautiful -->
|
:items="routeItems"
|
||||||
<v-breadcrumbs :items="routeItems">
|
v-if="routeItems.length != 0 && routeItems[0] != ''"
|
||||||
|
>
|
||||||
<template v-slot:title="{ item }">
|
<template v-slot:title="{ item }">
|
||||||
<v-card variant="outlined" class="pa-2" rounded="0">
|
<v-card variant="outlined" class="pa-2" rounded="0">
|
||||||
{{ item.title.charAt(0).toUpperCase() + item.title.slice(1) }}
|
{{ item.title.charAt(0).toUpperCase() + item.title.slice(1) }}
|
||||||
|
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -43,9 +43,11 @@ watch(() => route.path, () => {
|
|||||||
</template>
|
</template>
|
||||||
</v-breadcrumbs>
|
</v-breadcrumbs>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
<v-col>
|
<!-- Attributes -->
|
||||||
Filter:
|
<v-row>
|
||||||
|
<v-col class="d-flex justify-center">
|
||||||
<div v-for="query in route.query" v-html="query" />
|
<div v-for="query in route.query" v-html="query" />
|
||||||
|
|
||||||
<!-- Logic to check, if exercise 3.1 is solved -->
|
<!-- Logic to check, if exercise 3.1 is solved -->
|
||||||
@@ -55,14 +57,6 @@ watch(() => route.path, () => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-spacer />
|
|
||||||
</v-row>
|
|
||||||
|
|
||||||
<v-row class="pa-0 ma-0">
|
|
||||||
<v-col class="text-center">
|
|
||||||
{{ new Date().getFullYear() }} — <strong>Tobias Zoghaib</strong>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-container>
|
</v-container>
|
||||||
</v-footer>
|
</v-footer>
|
||||||
|
|||||||
21
software/src/components/navigation/navigationBar.vue
Normal file
21
software/src/components/navigation/navigationBar.vue
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import navigationPrependItems from './navigationPrependItems.vue';
|
||||||
|
import navigationAppendItems from './navigationAppendItems.vue';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<v-app-bar
|
||||||
|
height="80"
|
||||||
|
color="primary"
|
||||||
|
class="px-5"
|
||||||
|
elevation="0"
|
||||||
|
>
|
||||||
|
<template #prepend>
|
||||||
|
<navigation-prepend-items />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #append>
|
||||||
|
<navigation-append-items />
|
||||||
|
</template>
|
||||||
|
</v-app-bar>
|
||||||
|
</template>
|
||||||
@@ -1,7 +1,4 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -14,30 +11,69 @@ const router = useRouter()
|
|||||||
>
|
>
|
||||||
<v-img src="logo.png" width="80" />
|
<v-img src="logo.png" width="80" />
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|
||||||
|
<div class="d-md-none">
|
||||||
|
|
||||||
<v-divider vertical />
|
<v-menu>
|
||||||
|
<template #activator="{ props }">
|
||||||
|
<v-btn
|
||||||
|
icon="mdi-menu"
|
||||||
|
v-bind="props"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<v-list>
|
||||||
|
<v-list-item
|
||||||
|
to="/bands"
|
||||||
|
prepend-icon="mdi-guitar-electric"
|
||||||
|
>
|
||||||
|
{{ $t('band.allBands', 2) }}
|
||||||
|
</v-list-item>
|
||||||
|
|
||||||
|
<v-list-item
|
||||||
|
to="/concerts"
|
||||||
|
prepend-icon="mdi-ticket"
|
||||||
|
>
|
||||||
|
{{ $t('concert.allConcerts', 2) }}
|
||||||
|
</v-list-item>
|
||||||
|
|
||||||
|
<v-list-item
|
||||||
|
to="/locations"
|
||||||
|
prepend-icon="mdi-city"
|
||||||
|
>
|
||||||
|
{{ $t('location.allLocations', 2) }}
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-menu>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<v-divider vertical class="d-none d-md-flex" />
|
||||||
|
|
||||||
<v-btn
|
<v-btn
|
||||||
to="/bands"
|
to="/bands"
|
||||||
prepend-icon="mdi-guitar-electric"
|
prepend-icon="mdi-guitar-electric"
|
||||||
height="100%"
|
height="100%"
|
||||||
:rounded="false"
|
:rounded="false"
|
||||||
|
class="d-none d-md-flex"
|
||||||
>
|
>
|
||||||
{{ $t('band.allBands', 2) }}
|
{{ $t('band.allBands', 2) }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<v-divider vertical />
|
<v-divider vertical class="d-none d-md-flex" />
|
||||||
|
|
||||||
<v-btn
|
<v-btn
|
||||||
to="/concerts"
|
to="/concerts"
|
||||||
prepend-icon="mdi-ticket"
|
prepend-icon="mdi-ticket"
|
||||||
height="100%"
|
height="100%"
|
||||||
:rounded="false"
|
:rounded="false"
|
||||||
|
class="d-none d-md-flex"
|
||||||
>
|
>
|
||||||
{{ $t('concert.allConcerts', 2) }}
|
{{ $t('concert.allConcerts', 2) }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<v-divider vertical />
|
<v-divider vertical class="d-none d-lg-flex" />
|
||||||
|
|
||||||
|
|
||||||
<v-btn
|
<v-btn
|
||||||
@@ -45,9 +81,10 @@ const router = useRouter()
|
|||||||
prepend-icon="mdi-city"
|
prepend-icon="mdi-city"
|
||||||
height="100%"
|
height="100%"
|
||||||
:rounded="false"
|
:rounded="false"
|
||||||
|
class="d-none d-md-flex"
|
||||||
>
|
>
|
||||||
{{ $t('location.allLocations', 2) }}
|
{{ $t('location.allLocations', 2) }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<v-divider vertical />
|
<v-divider vertical class="d-none d-md-flex" />
|
||||||
</template>
|
</template>
|
||||||
@@ -19,9 +19,12 @@ watch(() => router.currentRoute.value.fullPath, () => {
|
|||||||
elevation="0"
|
elevation="0"
|
||||||
height="50"
|
height="50"
|
||||||
>
|
>
|
||||||
<v-row>
|
<v-row no-gutters>
|
||||||
<v-col></v-col>
|
<v-spacer />
|
||||||
<v-col cols="auto" class="d-flex justify-start align-center">
|
<v-col
|
||||||
|
cols="2"
|
||||||
|
class="d-flex justify-end align-center pr-1"
|
||||||
|
>
|
||||||
<v-btn
|
<v-btn
|
||||||
density="comfortable"
|
density="comfortable"
|
||||||
icon="mdi-arrow-left"
|
icon="mdi-arrow-left"
|
||||||
@@ -32,11 +35,7 @@ watch(() => router.currentRoute.value.fullPath, () => {
|
|||||||
icon="mdi-arrow-right"
|
icon="mdi-arrow-right"
|
||||||
@click="router.go(1)"
|
@click="router.go(1)"
|
||||||
/>
|
/>
|
||||||
<v-btn
|
|
||||||
density="comfortable"
|
|
||||||
icon="mdi-refresh"
|
|
||||||
@click="router.replace({ path: router.currentRoute.value.fullPath })"
|
|
||||||
/>
|
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="8">
|
<v-col cols="8">
|
||||||
@@ -49,12 +48,20 @@ watch(() => router.currentRoute.value.fullPath, () => {
|
|||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="2" class="d-flex justify-start align-center">
|
<v-col
|
||||||
|
cols="2"
|
||||||
|
class="d-flex justify-start align-center pl-1"
|
||||||
|
>
|
||||||
<v-btn
|
<v-btn
|
||||||
density="comfortable"
|
density="comfortable"
|
||||||
icon="mdi-arrow-right"
|
icon="mdi-arrow-right"
|
||||||
@click="navigate"
|
@click="navigate"
|
||||||
/>
|
/>
|
||||||
|
<v-btn
|
||||||
|
density="comfortable"
|
||||||
|
icon="mdi-refresh"
|
||||||
|
@click="router.replace({ path: router.currentRoute.value.fullPath })"
|
||||||
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ defineProps({
|
|||||||
<div class="position-absolute bottom-0 pa-5" style="width: 100%;">
|
<div class="position-absolute bottom-0 pa-5" style="width: 100%;">
|
||||||
<v-row>
|
<v-row>
|
||||||
<!-- Logo -->
|
<!-- Logo -->
|
||||||
<v-col cols="2">
|
<v-col cols="2 d-none d-md-block">
|
||||||
<v-skeleton-loader
|
<v-skeleton-loader
|
||||||
type="image"
|
type="image"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
import { ExerciseModel } from "./exerciseModel";
|
|
||||||
import { ExerciseGroupModel } from "./exerciseGroupModel";
|
|
||||||
|
|
||||||
export class ExerciseGroupApiModel extends ExerciseGroupModel {
|
|
||||||
exercises: Array<ExerciseModel>
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { ExerciseGroupModel } from "./exerciseGroupModel"
|
||||||
|
|
||||||
export class ExerciseModel {
|
export class ExerciseModel {
|
||||||
id = -1
|
id = -1
|
||||||
nameDe: string = ""
|
nameDe: string = ""
|
||||||
@@ -6,4 +8,5 @@ export class ExerciseModel {
|
|||||||
descriptionDe: string = ""
|
descriptionDe: string = ""
|
||||||
descriptionEn: string = ""
|
descriptionEn: string = ""
|
||||||
solved: boolean = false
|
solved: boolean = false
|
||||||
|
exerciseGroup: ExerciseGroupModel
|
||||||
}
|
}
|
||||||
@@ -162,7 +162,7 @@
|
|||||||
"help": {
|
"help": {
|
||||||
"scoreBoard": {
|
"scoreBoard": {
|
||||||
"exerciseGroupNr": "Aufgabengruppe {0}: ",
|
"exerciseGroupNr": "Aufgabengruppe {0}: ",
|
||||||
"exerciseNr": "Aufgabe {0}"
|
"exerciseNr": "Aufgabe {0}.{1}: "
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bannerMessages": {
|
"bannerMessages": {
|
||||||
|
|||||||
@@ -162,7 +162,7 @@
|
|||||||
"help": {
|
"help": {
|
||||||
"scoreBoard": {
|
"scoreBoard": {
|
||||||
"exerciseGroupNr": "Exercise Group {0}: ",
|
"exerciseGroupNr": "Exercise Group {0}: ",
|
||||||
"exerciseNr": "Exercise {0}"
|
"exerciseNr": "Exercise {0}.{1}: "
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bannerMessages": {
|
"bannerMessages": {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const bandStore = useBandStore()
|
|||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
<v-row v-if="bandStore.fetchInProgress" >
|
<v-row v-if="bandStore.fetchInProgress" >
|
||||||
<v-col cols="3" v-for="i in 4">
|
<v-col cols="6" md="3" v-for="i in 4">
|
||||||
<card-with-top-image :loading="true" />
|
<card-with-top-image :loading="true" />
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
@@ -22,7 +22,7 @@ const bandStore = useBandStore()
|
|||||||
<v-row>
|
<v-row>
|
||||||
<v-spacer />
|
<v-spacer />
|
||||||
|
|
||||||
<v-col v-for="member of bandStore.band.members" cols="3">
|
<v-col v-for="member of bandStore.band.members" cols="6" md="3">
|
||||||
<card-with-top-image
|
<card-with-top-image
|
||||||
:title="member.name"
|
:title="member.name"
|
||||||
:image=" member.image"
|
:image=" member.image"
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const bandStore = useBandStore()
|
|||||||
show-arrows
|
show-arrows
|
||||||
hide-delimiter-background
|
hide-delimiter-background
|
||||||
hide-delimiters
|
hide-delimiters
|
||||||
height="900"
|
max-height="900"
|
||||||
>
|
>
|
||||||
<template #prev="{ props }">
|
<template #prev="{ props }">
|
||||||
<v-btn
|
<v-btn
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ locationStore.getLocations()
|
|||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col class="text-center" v-for="i in 4" cols="3">
|
<v-col class="text-center" v-for="i in 4" cols="6" md="3">
|
||||||
<card-with-top-image :loading="true" />
|
<card-with-top-image :loading="true" />
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
@@ -48,7 +48,8 @@ locationStore.getLocations()
|
|||||||
<v-row>
|
<v-row>
|
||||||
<v-col
|
<v-col
|
||||||
v-for="location in locationStore.getLocationsByCity(city.name)"
|
v-for="location in locationStore.getLocationsByCity(city.name)"
|
||||||
cols="3"
|
cols="6"
|
||||||
|
md="3"
|
||||||
>
|
>
|
||||||
<location-list-item
|
<location-list-item
|
||||||
:location="location"
|
:location="location"
|
||||||
|
|||||||
@@ -1,14 +1,24 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import scoreCard from './scoreCard.vue';
|
|
||||||
import { useExerciseStore } from '@/stores/exercise.store';
|
import { useExerciseStore } from '@/stores/exercise.store';
|
||||||
import outlinedButton from '@/components/basics/outlinedButton.vue';
|
import outlinedButton from '@/components/basics/outlinedButton.vue';
|
||||||
import { generateResultsPdf } from '@/scripts/pdfScripts';
|
import { generateResultsPdf } from '@/scripts/pdfScripts';
|
||||||
import { usePreferencesStore } from '@/stores/preferences.store';
|
import { usePreferencesStore } from '@/stores/preferences.store';
|
||||||
|
import cardView from '@/components/basics/cardView.vue';
|
||||||
|
import { LanguageEnum } from '@/data/enums/languageEnum';
|
||||||
|
|
||||||
const exerciseStore = useExerciseStore()
|
const exerciseStore = useExerciseStore()
|
||||||
const preferencesStore = usePreferencesStore()
|
const preferencesStore = usePreferencesStore()
|
||||||
|
|
||||||
exerciseStore.getAllExercises()
|
exerciseStore.getAllExercises()
|
||||||
|
|
||||||
|
function getDotColor(exerciseGroupNr: number) {
|
||||||
|
switch(exerciseGroupNr) {
|
||||||
|
case 0: return "purple"
|
||||||
|
case 1: return "orange"
|
||||||
|
case 2: return "blue"
|
||||||
|
case 3: return "pink"
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -26,18 +36,50 @@ exerciseStore.getAllExercises()
|
|||||||
</outlined-button>
|
</outlined-button>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
<v-row v-if="exerciseStore.fetchInProgress" v-for="i in 3">
|
|
||||||
<v-col>
|
|
||||||
<score-card :loading="true"
|
|
||||||
/>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
|
|
||||||
<v-row v-for="exerciseGroup in exerciseStore.exerciseGroups">
|
<v-row>
|
||||||
<v-col>
|
<v-col>
|
||||||
<score-card
|
<card-view
|
||||||
:exercise-group="exerciseGroup"
|
:title="$t('misc.firstStartup.exercises')"
|
||||||
/>
|
icon="mdi-checkbox-marked-circle-auto-outline"
|
||||||
|
>
|
||||||
|
<template #borderless>
|
||||||
|
<v-timeline
|
||||||
|
side="end"
|
||||||
|
class="px-5"
|
||||||
|
align="start"
|
||||||
|
>
|
||||||
|
<v-timeline-item
|
||||||
|
v-for="exercise of exerciseStore.exercises"
|
||||||
|
:dot-color="getDotColor(exercise.exerciseGroup.groupNr)"
|
||||||
|
:icon="exercise.solved ? 'mdi-check' : 'mdi-pencil'"
|
||||||
|
>
|
||||||
|
<!-- Left side -->
|
||||||
|
<template #opposite>
|
||||||
|
<div
|
||||||
|
v-if="exercise.exerciseNr == 1"
|
||||||
|
:class="`pt-1 font-weight-bold text-${getDotColor(exercise.exerciseGroup.groupNr)}`"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
(preferencesStore.language == LanguageEnum.GERMAN
|
||||||
|
? exercise.exerciseGroup.nameDe
|
||||||
|
: exercise.exerciseGroup.nameEn)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Right side -->
|
||||||
|
<card-view
|
||||||
|
:title="$t('help.scoreBoard.exerciseNr', [exercise.exerciseGroup.groupNr, exercise.exerciseNr]) +
|
||||||
|
(preferencesStore.language == LanguageEnum.GERMAN ? exercise.nameDe : exercise.nameEn)"
|
||||||
|
:color="exercise.solved ? 'green' : 'primary'"
|
||||||
|
>
|
||||||
|
{{ preferencesStore.language == LanguageEnum.GERMAN ? exercise.descriptionDe : exercise.descriptionEn }}
|
||||||
|
</card-view>
|
||||||
|
</v-timeline-item>
|
||||||
|
</v-timeline>
|
||||||
|
</template>
|
||||||
|
</card-view>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-container>
|
</v-container>
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import cardView from '@/components/basics/cardView.vue';
|
|
||||||
import { LanguageEnum } from '@/data/enums/languageEnum';
|
|
||||||
import { ExerciseGroupApiModel } from '@/data/models/exercises/exerciseGroupApiModel';
|
|
||||||
import { usePreferencesStore } from '@/stores/preferences.store';
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
exerciseGroup: ExerciseGroupApiModel,
|
|
||||||
loading: Boolean
|
|
||||||
})
|
|
||||||
|
|
||||||
const preferencesStore = usePreferencesStore()
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<card-view v-if="loading" :loading="loading" >
|
|
||||||
<v-timeline
|
|
||||||
direction="horizontal"
|
|
||||||
side="start"
|
|
||||||
class="pb-3"
|
|
||||||
>
|
|
||||||
<v-timeline-item
|
|
||||||
v-for="i in 3"
|
|
||||||
dot-color="grey"
|
|
||||||
icon="mdi-pencil"
|
|
||||||
>
|
|
||||||
<v-skeleton-loader
|
|
||||||
type="list-item"
|
|
||||||
:loading="loading"
|
|
||||||
width="200"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<template #opposite>
|
|
||||||
<v-skeleton-loader
|
|
||||||
type="sentences"
|
|
||||||
:loading="loading"
|
|
||||||
width="200"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</v-timeline-item>
|
|
||||||
</v-timeline>
|
|
||||||
</card-view>
|
|
||||||
|
|
||||||
<card-view
|
|
||||||
v-else
|
|
||||||
:title="$t('help.scoreBoard.exerciseGroupNr', [exerciseGroup.groupNr]) +
|
|
||||||
(preferencesStore.language == LanguageEnum.GERMAN ? exerciseGroup.nameDe : exerciseGroup.nameEn)"
|
|
||||||
:loading="loading"
|
|
||||||
>
|
|
||||||
<template #borderless>
|
|
||||||
<v-timeline
|
|
||||||
direction="horizontal"
|
|
||||||
side="start"
|
|
||||||
class="pt-3"
|
|
||||||
>
|
|
||||||
<v-timeline-item
|
|
||||||
v-for="exercise in exerciseGroup.exercises"
|
|
||||||
:dot-color="exercise.solved ? 'green' : 'grey'"
|
|
||||||
:icon="exercise.solved ? 'mdi-check' : 'mdi-pencil'"
|
|
||||||
>
|
|
||||||
<v-skeleton-loader
|
|
||||||
type="text"
|
|
||||||
:loading="loading"
|
|
||||||
>
|
|
||||||
<div class="text-h6">
|
|
||||||
{{ $t('help.scoreBoard.exerciseNr', [exercise.exerciseNr]) }}
|
|
||||||
</div>
|
|
||||||
</v-skeleton-loader>
|
|
||||||
|
|
||||||
|
|
||||||
<template #opposite>
|
|
||||||
<v-skeleton-loader
|
|
||||||
type="text"
|
|
||||||
:loading="loading"
|
|
||||||
>
|
|
||||||
<div class="text-center pb-3">
|
|
||||||
<div class="text-h6">
|
|
||||||
{{ (preferencesStore.language == LanguageEnum.GERMAN ? exercise.nameDe : exercise.nameEn) }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
{{ (preferencesStore.language == LanguageEnum.GERMAN ?
|
|
||||||
exercise.descriptionDe : exercise.descriptionEn) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</v-skeleton-loader>
|
|
||||||
</template>
|
|
||||||
</v-timeline-item>
|
|
||||||
</v-timeline>
|
|
||||||
</template>
|
|
||||||
</card-view>
|
|
||||||
</template>
|
|
||||||
@@ -17,11 +17,21 @@ const locationStore = useLocationStore()
|
|||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col v-if="locationStore.fetchInProgress" v-for="n in 8" cols="3">
|
<v-col
|
||||||
|
v-if="locationStore.fetchInProgress"
|
||||||
|
v-for="n in 8"
|
||||||
|
cols="6"
|
||||||
|
md="3"
|
||||||
|
>
|
||||||
<card-view-top-image :loading="true" />
|
<card-view-top-image :loading="true" />
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col v-else v-for="location in locationStore.topLocations" cols="3">
|
<v-col
|
||||||
|
v-else
|
||||||
|
v-for="location in locationStore.topLocations"
|
||||||
|
cols="6"
|
||||||
|
md="3"
|
||||||
|
>
|
||||||
<card-view-top-image
|
<card-view-top-image
|
||||||
:image="location.imageOutdoor"
|
:image="location.imageOutdoor"
|
||||||
:title="location.name"
|
:title="location.name"
|
||||||
|
|||||||
@@ -18,17 +18,23 @@ const router = useRouter()
|
|||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col v-if="concertStore.fetchInProgress" v-for="n in 4" cols="3">
|
<v-col v-if="concertStore.fetchInProgress" v-for="n in 4" cols="6" md="3">
|
||||||
<card-view-top-image :loading="true" />
|
<card-view-top-image :loading="true" />
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col v-else v-for="concert in concertStore.upcomingConcerts" cols="3">
|
<v-col
|
||||||
|
v-else
|
||||||
|
v-for="concert in concertStore.upcomingConcerts"
|
||||||
|
cols="6"
|
||||||
|
md="3"
|
||||||
|
>
|
||||||
<card-view-top-image
|
<card-view-top-image
|
||||||
:image="concert.image"
|
:image="concert.image"
|
||||||
:title="moment(concert.date).format('DD.MM.YYYY')"
|
:title="moment(concert.date).format('DD.MM.YYYY')"
|
||||||
smaller-title
|
smaller-title
|
||||||
@click="router.push('/bands/details/' + concert.band.name.replaceAll(' ', '-').toLowerCase())"
|
@click="router.push('/bands/details/' + concert.band.name.replaceAll(' ', '-').toLowerCase())"
|
||||||
:loading="concertStore.fetchInProgress"
|
:loading="concertStore.fetchInProgress"
|
||||||
|
class="h-100"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
{{ concert.name }}
|
{{ concert.name }}
|
||||||
|
|||||||
@@ -122,7 +122,8 @@ const searchStore = useSearchStore()
|
|||||||
v-else-if="searchStore.locations.length > 0"
|
v-else-if="searchStore.locations.length > 0"
|
||||||
>
|
>
|
||||||
<v-col
|
<v-col
|
||||||
cols="3"
|
cols="6"
|
||||||
|
md="3"
|
||||||
v-for="location in searchStore.locations"
|
v-for="location in searchStore.locations"
|
||||||
>
|
>
|
||||||
<location-list-item
|
<location-list-item
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { fetchAllExerciseGroups, updateExercise } from "@/data/api/exerciseApi";
|
import { fetchAllExerciseGroups, updateExercise } from "@/data/api/exerciseApi";
|
||||||
import { ExerciseGroupApiModel } from "@/data/models/exercises/exerciseGroupApiModel";
|
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { useFeedbackStore } from "./feedback.store";
|
import { useFeedbackStore } from "./feedback.store";
|
||||||
import { BannerStateEnum } from "@/data/enums/bannerStateEnum";
|
import { BannerStateEnum } from "@/data/enums/bannerStateEnum";
|
||||||
|
import { ExerciseModel } from "@/data/models/exercises/exerciseModel";
|
||||||
|
|
||||||
export const useExerciseStore = defineStore("exerciseStore", {
|
export const useExerciseStore = defineStore("exerciseStore", {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
/** All exercise groups with sub-exercises */
|
/** All exercise groups with sub-exercises */
|
||||||
exerciseGroups: ref<Array<ExerciseGroupApiModel>>([]),
|
exercises: ref<Array<ExerciseModel>>([]),
|
||||||
|
|
||||||
/** Request to server sent, waiting for data response */
|
/** Request to server sent, waiting for data response */
|
||||||
fetchInProgress: ref(false)
|
fetchInProgress: ref(false)
|
||||||
@@ -23,7 +23,7 @@ export const useExerciseStore = defineStore("exerciseStore", {
|
|||||||
|
|
||||||
await fetchAllExerciseGroups()
|
await fetchAllExerciseGroups()
|
||||||
.then(result => {
|
.then(result => {
|
||||||
this.exerciseGroups = result.data
|
this.exercises = result.data
|
||||||
this.fetchInProgress = false
|
this.fetchInProgress = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user