Welcome dialog: New page for look and feel, redesign pages, merge database and exercise creating in one step

This commit is contained in:
2025-07-05 14:35:48 +02:00
parent 48c59936ec
commit b69c63ea53
8 changed files with 196 additions and 88 deletions

View File

@@ -229,6 +229,7 @@
"cancel": "Abbrechen", "cancel": "Abbrechen",
"more": "Mehr", "more": "Mehr",
"confirm": "Bestätigen", "confirm": "Bestätigen",
"back": "Zurück",
"next": "Weiter" "next": "Weiter"
}, },
"validation": { "validation": {
@@ -245,7 +246,7 @@
"firstStartup": { "firstStartup": {
"title": "Ersteinrichtung", "title": "Ersteinrichtung",
"description": "Die Datenbank wird eingerichtet. Bitte warten...", "description": "Die Datenbank wird eingerichtet. Bitte warten...",
"createDatabase": "Erstelle Datenbank...", "createDatabase": "Datenbank Einrichtung",
"complete": "Fertig", "complete": "Fertig",
"finished": "Abgeschlossen", "finished": "Abgeschlossen",
"createExercises": "Erstelle Aufgaben...", "createExercises": "Erstelle Aufgaben...",
@@ -253,6 +254,7 @@
"database": "Datenbank", "database": "Datenbank",
"exercises": "Aufgaben", "exercises": "Aufgaben",
"userData": "Persönliche Daten", "userData": "Persönliche Daten",
"lookAndFeel": "Look and feel",
"enterYourPersonalData": "Bitte gebe nun deinen Namen und deine Matrikelnummer von der Universität ein. Überprüfe die Angaben vor dem Absenden genau! Die Angaben können später nicht ohne Verlust des Bearbeitungsfortschrittes geändert werden!" "enterYourPersonalData": "Bitte gebe nun deinen Namen und deine Matrikelnummer von der Universität ein. Überprüfe die Angaben vor dem Absenden genau! Die Angaben können später nicht ohne Verlust des Bearbeitungsfortschrittes geändert werden!"
}, },
"user": "Angaben zur Person", "user": "Angaben zur Person",

View File

@@ -229,6 +229,7 @@
"cancel": "Cancel", "cancel": "Cancel",
"more": "More", "more": "More",
"confirm": "Confirm", "confirm": "Confirm",
"back": "Back",
"next": "Next" "next": "Next"
}, },
"validation": { "validation": {
@@ -245,14 +246,13 @@
"firstStartup": { "firstStartup": {
"title": "First startup", "title": "First startup",
"description": "Creating database. Please wait...", "description": "Creating database. Please wait...",
"createDatabase": "Create Database...", "createDatabase": "Create Database",
"complete": "Complete", "complete": "Complete",
"createExercises": "Create Exercises...",
"finished": "Finished",
"connectToServer": "Server", "connectToServer": "Server",
"database": "Database", "database": "Database",
"exercises": "Exercises", "exercises": "Exercises",
"userData": "User data", "userData": "User data",
"lookAndFeel": "Look and feel",
"enterYourPersonalData": "Please enter your name and your Matrikel number from your university. Check it twice! You can't change it later without loosing your exercise progress!" "enterYourPersonalData": "Please enter your name and your Matrikel number from your university. Check it twice! You can't change it later without loosing your exercise progress!"
}, },
"user": "About person", "user": "About person",

View File

@@ -5,7 +5,7 @@ import bandSection from './bandsSection.vue';
import UpcomingConcertsSection from './upcomingConcertsSection.vue'; import UpcomingConcertsSection from './upcomingConcertsSection.vue';
import TopLocationsSection from './topLocationsSection.vue'; import TopLocationsSection from './topLocationsSection.vue';
import { usePreferencesStore } from '@/stores/preferences.store'; import { usePreferencesStore } from '@/stores/preferences.store';
import welcomeDialog from './welcomeDialog.vue'; import welcomeDialog from './welcomeDialog/dialog.vue';
import { ref } from 'vue'; import { ref } from 'vue';
const concertStore = useConcertStore() const concertStore = useConcertStore()
@@ -17,8 +17,8 @@ concertStore.getUpcomingConcerts()
locationStore.getTopLocations() locationStore.getTopLocations()
// First startup // First startup
if (preferencesStore.firstStartup) {
showWelcomeDialog.value = true showWelcomeDialog.value = true
if (preferencesStore.firstStartup) {
} }
</script> </script>

View File

@@ -1,43 +1,36 @@
<script setup lang="ts"> <script setup lang="ts">
import actionDialog from '@/components/basics/actionDialog.vue'; import actionDialog from '@/components/basics/actionDialog.vue';
import outlinedButton from '@/components/basics/outlinedButton.vue'; import outlinedButton from '@/components/basics/outlinedButton.vue';
import ServerStateText from '@/components/pageParts/serverStateText.vue';
import { getRegisterNumberRules, getStringRules } from '@/scripts/validationRules';
import { useFeedbackStore } from '@/stores/feedback.store'; import { useFeedbackStore } from '@/stores/feedback.store';
import { usePreferencesStore } from '@/stores/preferences.store'; import { usePreferencesStore } from '@/stores/preferences.store';
import { ref, watch } from 'vue'; import { ref, watch } from 'vue';
import step1 from './step1.vue';
import step2 from './step2.vue';
import step3 from './step3.vue';
import step4 from './step4.vue';
const preferencesStore = usePreferencesStore() const preferencesStore = usePreferencesStore()
const feedbackStore = useFeedbackStore() const feedbackStore = useFeedbackStore()
const showDialog = defineModel() const showDialog = defineModel()
const currentStep = ref(0) const currentStep = ref(1)
const databaseCreated = ref(false)
const steps = [ const steps = [
feedbackStore.i18n.t('misc.firstStartup.connectToServer'), feedbackStore.i18n.t('misc.firstStartup.connectToServer'),
feedbackStore.i18n.t('misc.firstStartup.lookAndFeel'),
feedbackStore.i18n.t('misc.firstStartup.database'), feedbackStore.i18n.t('misc.firstStartup.database'),
feedbackStore.i18n.t('misc.firstStartup.exercises'),
feedbackStore.i18n.t('misc.firstStartup.userData'), feedbackStore.i18n.t('misc.firstStartup.userData'),
] ]
preferencesStore.getServerState() preferencesStore.getServerState()
watch(() => currentStep.value, () => { watch(() => currentStep.value, async () => {
switch(currentStep.value) { if (currentStep.value == 3 && !databaseCreated.value) {
case 2: { await preferencesStore.resetDb();
preferencesStore.resetDb(); await preferencesStore.resetExerciseProg();
break;
}
case 3: { databaseCreated.value = true;
preferencesStore.resetExerciseProg();
break;
}
case 4: {
break;
}
} }
}) })
</script> </script>
@@ -77,83 +70,31 @@ watch(() => currentStep.value, () => {
<!-- Step 1: Check connection to backend server --> <!-- Step 1: Check connection to backend server -->
<v-stepper-window-item <v-stepper-window-item
:value="1" :value="1"
class="text-h4 text-center"
> >
<div> <step1 />
{{ $t('preferences.serverState') + ':' }}
</div>
<server-state-text />
</v-stepper-window-item> </v-stepper-window-item>
<!-- Step 2: Reset the database -->
<!-- Step 2: Select theme and language -->
<v-stepper-window-item <v-stepper-window-item
:value="2" :value="2"
> >
<div v-if="preferencesStore.fetchInProgress" class="text-center text-h4 pb-4"> <step2 />
<div class="pb-4">
{{ $t('misc.firstStartup.createDatabase') }}
</div>
<v-progress-linear indeterminate />
</div>
<div v-else class="text-center text-h4 pb-4 text-green">
<v-icon icon="mdi-check" /> {{ $t('misc.firstStartup.finished') }}
</div>
</v-stepper-window-item> </v-stepper-window-item>
<!-- Step 3: Create exercises --> <!-- Step 3: Reset the database -->
<v-stepper-window-item <v-stepper-window-item
:value="3" :value="3"
> >
<div v-if="preferencesStore.fetchInProgress" class="text-center text-h4 pb-4"> <step3 />
<div class="pb-4">
{{ $t('misc.firstStartup.createExercises') }}
</div>
<v-progress-linear indeterminate />
</div>
<div v-else class="text-center text-h4 pb-4 text-green">
<v-icon icon="mdi-check" /> {{ $t('misc.firstStartup.finished') }}
</div>
</v-stepper-window-item> </v-stepper-window-item>
<!-- Step 4: Personal data --> <!-- Step 4: Personal data -->
<v-stepper-window-item <v-stepper-window-item
:value="4" :value="4"
> >
<v-container class="px-0 py-2"> <step4 />
<v-row>
<v-col>
<v-alert color="warning" icon="mdi-alert">
{{ $t('misc.firstStartup.enterYourPersonalData') }}
</v-alert>
</v-col>
</v-row>
<v-row>
<v-col>
<v-text-field
variant="outlined"
:label="$t('misc.yourFullName')"
v-model="preferencesStore.studentName"
:rules="getStringRules(4)"
/>
</v-col>
</v-row>
<v-row>
<v-col>
<v-text-field
variant="outlined"
:label="$t('misc.registrationNumber')"
v-model="preferencesStore.registrationNumber"
:rules="getRegisterNumberRules()"
/>
</v-col>
</v-row>
</v-container>
</v-stepper-window-item> </v-stepper-window-item>
</v-stepper-window> </v-stepper-window>
@@ -161,16 +102,25 @@ watch(() => currentStep.value, () => {
<!-- Next/Previous buttons --> <!-- Next/Previous buttons -->
<v-stepper-actions <v-stepper-actions
@click:next="next" @click:next="next"
@click:prev="prev"
> >
<template #prev="{ props }"> <template #prev="{ props }">
<v-spacer /> <outlined-button
@click="props.onClick()"
:disabled="currentStep == 1 || preferencesStore.fetchInProgress"
color="grey"
prepend-icon="mdi-arrow-left"
>
{{ $t('misc.actions.back') }}
</outlined-button>
</template> </template>
<template #next="{ props }"> <template #next="{ props }">
<outlined-button <outlined-button
v-if="currentStep < 4" v-if="currentStep < steps.length"
@click="props.onClick()" @click="props.onClick()"
:disabled="preferencesStore.fetchInProgress" :disabled="preferencesStore.fetchInProgress"
append-icon="mdi-arrow-right"
> >
{{ $t('misc.actions.next') }} {{ $t('misc.actions.next') }}
</outlined-button> </outlined-button>
@@ -180,7 +130,7 @@ watch(() => currentStep.value, () => {
@click="showDialog = false; preferencesStore.firstStartup = false" @click="showDialog = false; preferencesStore.firstStartup = false"
:disabled="preferencesStore.studentName.length < 5 || :disabled="preferencesStore.studentName.length < 5 ||
preferencesStore.registrationNumber.length < 8" preferencesStore.registrationNumber.length < 8"
prepend-icon="mdi-check" append-icon="mdi-check"
color="success" color="success"
> >
{{ $t('misc.firstStartup.complete') }} {{ $t('misc.firstStartup.complete') }}

View File

@@ -0,0 +1,23 @@
<script setup lang="ts">
import ServerStateText from '@/components/pageParts/serverStateText.vue';
</script>
<template>
<v-container class="text-h4 text-center">
<v-row>
<v-col>
<v-icon icon="mdi-server" />
</v-col>
</v-row>
<v-row>
<v-col>
<div>
{{ $t('preferences.serverState') + ':' }}
</div>
<server-state-text />
</v-col>
</v-row>
</v-container>
</template>

View File

@@ -0,0 +1,48 @@
<script setup lang="ts">
import { ThemeEnum } from '@/data/enums/themeEnums';
import { usePreferencesStore } from '@/stores/preferences.store';
const preferencesStore = usePreferencesStore()
const themeEnums = Object.values(ThemeEnum)
</script>
<template>
<v-container width="600" class="text-h4 text-center">
<v-row>
<v-col>
<v-icon icon="mdi-palette" />
</v-col>
</v-row>
<v-row>
<v-col>
{{ $t('misc.firstStartup.lookAndFeel') }}
</v-col>
</v-row>
<v-row>
<v-col>
<v-select
v-model="preferencesStore.theme"
:items="themeEnums"
:label="$t('preferences.selectedTheme')"
variant="outlined"
hide-details
/>
</v-col>
</v-row>
<v-row>
<v-col>
<v-select
v-model="preferencesStore.language"
:items="$i18n.availableLocales"
:label="$t('preferences.language')"
variant="outlined"
hide-details
/>
</v-col>
</v-row>
</v-container>
</template>

View File

@@ -0,0 +1,31 @@
<script setup lang="ts">
import { usePreferencesStore } from '@/stores/preferences.store';
const preferencesStore = usePreferencesStore()
</script>
<template>
<v-container width="600" class="text-h4 text-center">
<v-row>
<v-col>
<v-icon icon="mdi-database" />
</v-col>
</v-row>
<v-row>
<v-col>
{{ $t('misc.firstStartup.createDatabase') }}
</v-col>
</v-row>
<v-row>
<v-col v-if="preferencesStore.fetchInProgress">
<v-progress-linear indeterminate />
</v-col>
<v-col v-else class="text-green">
<v-icon icon="mdi-check" /> {{ $t('misc.firstStartup.finished') }}
</v-col>
</v-row>
</v-container>
</template>

View File

@@ -0,0 +1,54 @@
<script setup lang="ts">
import { getRegisterNumberRules, getStringRules } from '@/scripts/validationRules';
import { usePreferencesStore } from '@/stores/preferences.store';
const preferencesStore = usePreferencesStore()
</script>
<template>
<v-container class="px-0 py-2" width="600">
<v-row>
<v-col class="text-h4 text-center">
<v-icon icon="mdi-account" />
</v-col>
</v-row>
<v-row>
<v-col class="text-h4 text-center">
{{ $t('misc.firstStartup.userData') }}
</v-col>
</v-row>
<v-row>
<v-col>
<v-alert color="warning" icon="mdi-alert">
{{ $t('misc.firstStartup.enterYourPersonalData') }}
</v-alert>
</v-col>
</v-row>
<v-row>
<v-col>
<v-text-field
variant="outlined"
:label="$t('misc.yourFullName')"
v-model="preferencesStore.studentName"
:rules="getStringRules(4)"
hide-details
/>
</v-col>
</v-row>
<v-row>
<v-col>
<v-text-field
variant="outlined"
:label="$t('misc.registrationNumber')"
v-model="preferencesStore.registrationNumber"
:rules="getRegisterNumberRules()"
hide-details
/>
</v-col>
</v-row>
</v-container>
</template>