Add query url and clickable navigation

This commit is contained in:
Daniel Egger 2023-05-09 18:13:09 +02:00
parent 6534cbf8df
commit 04b179aa52
4 changed files with 138 additions and 133 deletions

View File

@ -1,106 +1,3 @@
<template>
<LearningContentMultiLayout
:title="title"
subtitle="Feedback"
:learning-content-type="'feedback'"
:show-start-button="stepNo === 0"
:show-next-button="stepNo > 0 && stepNo + 1 < numSteps"
:show-previous-button="stepNo > 0"
:show-exit-button="stepNo + 1 === numSteps"
:current-step="stepNo"
:steps-count="numSteps"
:start-badge-text="$t('general.introduction')"
:end-badge-text="$t('general.submission')"
@previous="previousStep()"
@next="nextStep()"
>
<div>
<p v-if="stepNo === 0" class="mt-10">
{{
$t("feedback.intro", {
name: `${courseSessionsStore.circleExperts[0].first_name} ${courseSessionsStore.circleExperts[0].last_name}`,
})
}}
</p>
<p v-if="stepNo > 0 && stepNo + 1 < numSteps" class="pb-2">
{{ stepLabels[stepNo] }}
</p>
<ItRadioGroup
v-if="stepNo === 1"
v-model="satisfaction"
class="mb-8"
:items="RATINGS"
/>
<ItRadioGroup
v-if="stepNo === 2"
v-model="goalAttainment"
class="mb-8"
:items="RATINGS"
/>
<ItRadioGroup
v-if="stepNo === 3"
v-model="proficiency"
class="mb-8"
:items="PERCENTAGES"
/>
<ItRadioGroup
v-if="stepNo === 4"
v-model="preparationTaskClarity"
class="mb-8"
:items="YES_NO"
/>
<ItRadioGroup
v-if="stepNo === 5"
v-model="instructorCompetence"
class="mb-8"
:items="RATINGS"
/>
<ItRadioGroup
v-if="stepNo === 6"
v-model="instructorRespect"
class="mb-8"
:items="RATINGS"
/>
<ItTextarea v-if="stepNo === 7" v-model="instructorOpenFeedback" class="mb-8" />
<ItRadioGroup
v-if="stepNo === 8"
v-model="wouldRecommend"
class="mb-8"
:items="YES_NO"
/>
<ItTextarea v-if="stepNo === 9" v-model="courseNegativeFeedback" class="mb-8" />
<ItTextarea v-if="stepNo === 10" v-model="coursePositiveFeedback" class="mb-8" />
<FeedbackCompletition
v-if="stepNo === 11"
:avatar-url="courseSessionsStore.circleExperts[0].avatar_url"
:title="
$t('feedback.completionTitle', {
name: `${courseSessionsStore.circleExperts[0].first_name} ${courseSessionsStore.circleExperts[0].last_name}`,
})
"
:description="$t('feedback.completionDescription')"
:feedback-sent="mutationResult != null"
@send-feedback="sendFeedback"
/>
</div>
</LearningContentMultiLayout>
<!--
<pre>
satisfaction {{ satisfaction }}
goalAttainment {{ goalAttainment }}
proficiency {{ proficiency }}
receivedMaterials {{ receivedMaterials }}
materialsRating {{ materialsRating }}
instructorCompetence {{ instructorCompetence }}
instructorRespect {{ instructorRespect }}
instructorOpenFeedback {{ instructorOpenFeedback }}
wouldRecommend {{ wouldRecommend }}
coursePositiveFeedback {{ coursePositiveFeedback }}
courseNegativeFeedback {{ courseNegativeFeedback }}
mutationResult: {{ mutationResult }}
</pre> -->
</template>
<script setup lang="ts">
import ItRadioGroup from "@/components/ui/ItRadioGroup.vue";
import ItTextarea from "@/components/ui/ItTextarea.vue";
@ -117,6 +14,7 @@ import { useCircleStore } from "@/stores/circle";
import { useCourseSessionsStore } from "@/stores/courseSessions";
import type { LearningContent } from "@/types";
import { useMutation } from "@urql/vue";
import { useRouteQuery } from "@vueuse/router";
import log from "loglevel";
import { computed, onMounted, reactive, ref } from "vue";
import { useI18n } from "vue-i18n";
@ -130,7 +28,7 @@ onMounted(async () => {
log.debug("Feedback mounted");
});
const stepNo = ref(0);
const stepNo = useRouteQuery("step", "0", { transform: Number, mode: "push" });
const title = computed(
() => `«${circleStore.circle?.title}»: ${t("feedback.areYouSatisfied")}`
@ -229,3 +127,107 @@ const sendFeedback = () => {
.catch((e) => log.error(e));
};
</script>
<template>
<LearningContentMultiLayout
:title="title"
subtitle="Feedback"
:learning-content-type="'feedback'"
:show-start-button="stepNo === 0"
:show-next-button="stepNo > 0 && stepNo + 1 < numSteps"
:show-previous-button="stepNo > 0"
:show-exit-button="stepNo + 1 === numSteps"
:current-step="stepNo"
:steps-count="numSteps"
:start-badge-text="$t('general.introduction')"
:end-badge-text="$t('general.submission')"
:base-url="props.page.frontend_url"
@previous="previousStep()"
@next="nextStep()"
>
<div>
<p v-if="stepNo === 0" class="mt-10">
{{
$t("feedback.intro", {
name: `${courseSessionsStore.circleExperts[0].first_name} ${courseSessionsStore.circleExperts[0].last_name}`,
})
}}
</p>
<p v-if="stepNo > 0 && stepNo + 1 < numSteps" class="pb-2">
{{ stepLabels[stepNo] }}
</p>
<ItRadioGroup
v-if="stepNo === 1"
v-model="satisfaction"
class="mb-8"
:items="RATINGS"
/>
<ItRadioGroup
v-if="stepNo === 2"
v-model="goalAttainment"
class="mb-8"
:items="RATINGS"
/>
<ItRadioGroup
v-if="stepNo === 3"
v-model="proficiency"
class="mb-8"
:items="PERCENTAGES"
/>
<ItRadioGroup
v-if="stepNo === 4"
v-model="preparationTaskClarity"
class="mb-8"
:items="YES_NO"
/>
<ItRadioGroup
v-if="stepNo === 5"
v-model="instructorCompetence"
class="mb-8"
:items="RATINGS"
/>
<ItRadioGroup
v-if="stepNo === 6"
v-model="instructorRespect"
class="mb-8"
:items="RATINGS"
/>
<ItTextarea v-if="stepNo === 7" v-model="instructorOpenFeedback" class="mb-8" />
<ItRadioGroup
v-if="stepNo === 8"
v-model="wouldRecommend"
class="mb-8"
:items="YES_NO"
/>
<ItTextarea v-if="stepNo === 9" v-model="courseNegativeFeedback" class="mb-8" />
<ItTextarea v-if="stepNo === 10" v-model="coursePositiveFeedback" class="mb-8" />
<FeedbackCompletition
v-if="stepNo === 11"
:avatar-url="courseSessionsStore.circleExperts[0].avatar_url"
:title="
$t('feedback.completionTitle', {
name: `${courseSessionsStore.circleExperts[0].first_name} ${courseSessionsStore.circleExperts[0].last_name}`,
})
"
:description="$t('feedback.completionDescription')"
:feedback-sent="mutationResult != null"
@send-feedback="sendFeedback"
/>
</div>
</LearningContentMultiLayout>
<!--
<pre>
satisfaction {{ satisfaction }}
goalAttainment {{ goalAttainment }}
proficiency {{ proficiency }}
receivedMaterials {{ receivedMaterials }}
materialsRating {{ materialsRating }}
instructorCompetence {{ instructorCompetence }}
instructorRespect {{ instructorRespect }}
instructorOpenFeedback {{ instructorOpenFeedback }}
wouldRecommend {{ wouldRecommend }}
coursePositiveFeedback {{ coursePositiveFeedback }}
courseNegativeFeedback {{ courseNegativeFeedback }}
mutationResult: {{ mutationResult }}
</pre> -->
</template>

View File

@ -9,14 +9,14 @@ export interface Props {
startBadgeText?: string;
endBadgeText?: string;
baseUrl?: string;
queryParam?: string;
stepQueryParam?: string;
}
const props = withDefaults(defineProps<Props>(), {
startBadgeText: undefined,
endBadgeText: undefined,
baseUrl: undefined,
queryParam: "page",
stepQueryParam: "step",
});
const hasStartBadge = computed(() => typeof props.startBadgeText !== "undefined");
@ -67,7 +67,10 @@ function calcStepIndex(step: number) {
:class="startBadgeClasses"
data-cy="nav-progress-step-start"
>
<router-link v-if="props.baseUrl" :to="`${props.baseUrl}?${props.queryParam}=0`">
<router-link
v-if="props.baseUrl"
:to="`${props.baseUrl}?${props.stepQueryParam}=0`"
>
{{ props.startBadgeText }}
</router-link>
<span v-else>{{ props.startBadgeText }}</span>
@ -84,7 +87,7 @@ function calcStepIndex(step: number) {
>
<router-link
v-if="props.baseUrl"
:to="`${props.baseUrl}?${props.queryParam}=${calcStepIndex(step)}`"
:to="`${props.baseUrl}?${props.stepQueryParam}=${calcStepIndex(step)}`"
>
{{ step + 1 }}
</router-link>
@ -100,7 +103,7 @@ function calcStepIndex(step: number) {
>
<router-link
v-if="props.baseUrl"
:to="`${props.baseUrl}?${props.queryParam}=${steps - 1}`"
:to="`${props.baseUrl}?${props.stepQueryParam}=${steps - 1}`"
>
{{ props.endBadgeText }}
</router-link>

View File

@ -41,7 +41,7 @@ const props = defineProps<{
}>();
// 0 = introduction, 1 - n = tasks, n+1 = submission
const pageIndex = useRouteQuery("page", "0", { transform: Number, mode: "push" });
const stepIndex = useRouteQuery("step", "0", { transform: Number, mode: "push" });
const assignmentCompletion = computed(() => assignmentStore.assignmentCompletion);
const completionStatus = computed(() => {
@ -64,10 +64,10 @@ onMounted(async () => {
);
if (
pageIndex.value === 0 &&
stepIndex.value === 0 &&
(completionStatus.value ?? "in_progress") !== "in_progress"
) {
pageIndex.value = numPages.value - 1;
stepIndex.value = numPages.value - 1;
}
} catch (error) {
log.error(error);
@ -76,9 +76,9 @@ onMounted(async () => {
const numTasks = computed(() => state.assignment?.tasks?.length ?? 0);
const numPages = computed(() => numTasks.value + 2);
const showPreviousButton = computed(() => pageIndex.value != 0);
const showNextButton = computed(() => pageIndex.value + 1 < numPages.value);
const showExitButton = computed(() => numPages.value === pageIndex.value + 1);
const showPreviousButton = computed(() => stepIndex.value != 0);
const showNextButton = computed(() => stepIndex.value + 1 < numPages.value);
const showExitButton = computed(() => numPages.value === stepIndex.value + 1);
const dueDate = computed(() =>
dayjs(state.courseSessionAssignmentDetails?.submissionDeadlineDateTimeUtc)
);
@ -86,41 +86,41 @@ const courseSessionId = computed(
() => courseSessionsStore.currentCourseSession?.id ?? 0
);
const currentTask = computed(() => {
if (pageIndex.value > 0 && pageIndex.value <= numTasks.value) {
return state.assignment?.tasks[pageIndex.value - 1];
if (stepIndex.value > 0 && stepIndex.value <= numTasks.value) {
return state.assignment?.tasks[stepIndex.value - 1];
}
return undefined;
});
const handleBack = () => {
log.debug("handleBack");
if (pageIndex.value > 0) {
pageIndex.value -= 1;
if (stepIndex.value > 0) {
stepIndex.value -= 1;
}
log.debug(`pageIndex: ${pageIndex.value}`);
log.debug(`pageIndex: ${stepIndex.value}`);
};
const handleContinue = () => {
log.debug("handleContinue");
if (pageIndex.value + 1 < numPages.value) {
pageIndex.value += 1;
if (stepIndex.value + 1 < numPages.value) {
stepIndex.value += 1;
}
log.debug(`pageIndex: ${pageIndex.value}`);
log.debug(`pageIndex: ${stepIndex.value}`);
};
const jumpToTask = (task: AssignmentTask) => {
log.debug("jumpToTask", task);
const index = state.assignment?.tasks.findIndex((t) => t.id === task.id);
if (index && index >= 0) {
pageIndex.value = index + 1;
stepIndex.value = index + 1;
}
log.debug(`pageIndex: ${pageIndex.value}`);
log.debug(`pageIndex: ${stepIndex.value}`);
};
const getTitle = () => {
if (0 === pageIndex.value) {
if (0 === stepIndex.value) {
return t("general.introduction");
} else if (pageIndex.value === numPages.value - 1) {
} else if (stepIndex.value === numPages.value - 1) {
return t("general.submission");
}
return currentTask?.value?.value.title ?? "Unknown";
@ -137,7 +137,7 @@ const assignmentUser = computed(() => {
<div v-if="state.assignment">
<div class="flex">
<LearningContentMultiLayout
:current-step="pageIndex"
:current-step="stepIndex"
:subtitle="state.assignment?.title ?? ''"
:title="getTitle()"
learning-content-type="assignment"
@ -147,7 +147,7 @@ const assignmentUser = computed(() => {
:show-start-button="false"
:show-previous-button="showPreviousButton"
:base-url="props.learningContent.frontend_url"
query-param="page"
step-query-param="step"
start-badge-text="Einleitung"
end-badge-text="Abgabe"
close-button-variant="close"
@ -157,7 +157,7 @@ const assignmentUser = computed(() => {
<div class="flex">
<div>
<AssignmentIntroductionView
v-if="pageIndex === 0 && state.assignment"
v-if="stepIndex === 0 && state.assignment"
:due-date="dueDate"
:assignment="state.assignment!"
></AssignmentIntroductionView>
@ -167,7 +167,7 @@ const assignmentUser = computed(() => {
:assignment-id="props.assignmentId"
></AssignmentTaskView>
<AssignmentSubmissionView
v-if="pageIndex + 1 === numPages && state.assignment && courseSessionId"
v-if="stepIndex + 1 === numPages && state.assignment && courseSessionId"
:due-date="dueDate"
:assignment="state.assignment!"
:assignment-completion-data="assignmentCompletion?.completion_data ?? {}"

View File

@ -20,7 +20,7 @@ interface Props {
endBadgeText?: string;
closeButtonVariant?: ClosingButtonVariant;
baseUrl?: string;
queryParam?: string;
stepQueryParam?: string;
}
const props = withDefaults(defineProps<Props>(), {
@ -58,7 +58,7 @@ const emit = defineEmits(["previous", "next", "exit"]);
:steps="stepsCount"
:end-badge-text="props.endBadgeText"
:base-url="props.baseUrl"
:query-param="props.queryParam"
:query-param="props.stepQueryParam"
class="overflow-hidden pb-12"
></ItNavigationProgress>
<slot></slot>