fix: use ItDropdown, simplify UI state

This commit is contained in:
Livio Bieri 2024-02-05 17:37:01 +01:00
parent b44db0d788
commit 5d510e0d04
2 changed files with 40 additions and 47 deletions

View File

@ -4,11 +4,11 @@ import { useLearningMentors } from "@/composables";
import { computed, ref } from "vue"; import { computed, ref } from "vue";
import ItButton from "@/components/ui/ItButton.vue"; import ItButton from "@/components/ui/ItButton.vue";
import NoMentorInformationPanel from "@/components/mentor/NoMentorInformationPanel.vue"; import NoMentorInformationPanel from "@/components/mentor/NoMentorInformationPanel.vue";
import { useCSRFFetch } from "@/fetchHelpers";
import { useSelfEvaluationFeedback } from "@/services/selfEvaluationFeedback"; import { useSelfEvaluationFeedback } from "@/services/selfEvaluationFeedback";
import FeedbackRequestedInformationPanel from "@/components/selfEvaluationFeedback/FeedbackRequestedInformationPanel.vue"; import FeedbackRequestedInformationPanel from "@/components/selfEvaluationFeedback/FeedbackRequestedInformationPanel.vue";
import FeedbackReceived from "@/components/selfEvaluationFeedback/FeedbackReceived.vue"; import FeedbackReceived from "@/components/selfEvaluationFeedback/FeedbackReceived.vue";
import FeedbackRequested from "@/components/selfEvaluationFeedback/FeedbackRequested.vue"; import FeedbackRequested from "@/components/selfEvaluationFeedback/FeedbackRequested.vue";
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
const props = defineProps<{ const props = defineProps<{
learningUnit: LearningUnit; learningUnit: LearningUnit;
@ -21,13 +21,19 @@ const selfEvaluationFeedback = useSelfEvaluationFeedback(
); );
const storedFeedback = computed(() => selfEvaluationFeedback.feedback.value); const storedFeedback = computed(() => selfEvaluationFeedback.feedback.value);
const isStoredFeedbackLoading = computed(() => selfEvaluationFeedback.loading.value); const isStoredFeedbackLoading = computed(() => selfEvaluationFeedback.loading.value);
const feedbackProvider = computed(() => storedFeedback.value?.feedback_provider_user);
// if no feedback is stored "current session" state management (mentor selection etc.) // if no feedback is stored "current session" state management (mentor selection etc.)
const learningMentors = useLearningMentors(); const learningMentors = useLearningMentors();
const mentors = computed(() => learningMentors.learningMentors.value);
const isMentorsLoading = computed(() => learningMentors.loading.value); const isMentorsLoading = computed(() => learningMentors.loading.value);
const isCurrentSessionFeedbackRequested = ref(false); const mentors = computed(() => {
return learningMentors.learningMentors.value.map((mentor) => ({
id: mentor.mentor.id,
name: `${mentor.mentor.first_name} ${mentor.mentor.last_name}`,
}));
});
const currentSessionRequestedMentor = ref(); const currentSessionRequestedMentor = ref();
const VisualState = { const VisualState = {
@ -43,8 +49,6 @@ const currentVisualState = computed(() => {
return VisualState.LOADING; return VisualState.LOADING;
} else if (mentors.value.length == 0) { } else if (mentors.value.length == 0) {
return VisualState.NO_MENTOR; return VisualState.NO_MENTOR;
} else if (isCurrentSessionFeedbackRequested.value) {
return VisualState.HAS_REQUESTED_FEEDBACK;
} else if (storedFeedback.value && !storedFeedback.value.feedback_submitted) { } else if (storedFeedback.value && !storedFeedback.value.feedback_submitted) {
return VisualState.HAS_REQUESTED_FEEDBACK; return VisualState.HAS_REQUESTED_FEEDBACK;
} else if (storedFeedback.value && storedFeedback.value.feedback_submitted) { } else if (storedFeedback.value && storedFeedback.value.feedback_submitted) {
@ -54,30 +58,8 @@ const currentVisualState = computed(() => {
} }
}); });
const feedbackMentorName = computed(() => {
let mentor = null;
if (storedFeedback.value) {
mentor = storedFeedback.value.feedback_provider_user;
} else if (isCurrentSessionFeedbackRequested.value) {
mentor = currentSessionRequestedMentor.value;
}
if (mentor) {
return `${mentor.first_name} ${mentor.last_name}`;
} else {
return "";
}
});
const onRequestFeedback = async () => { const onRequestFeedback = async () => {
const url = `/api/self-evaluation-feedback/requester/${props.learningUnit.id}/feedback/start`; await selfEvaluationFeedback.requestFeedback(currentSessionRequestedMentor.value.id);
const { error } = await useCSRFFetch(url).post({
feedback_provider_user_id: currentSessionRequestedMentor.value.id,
});
if (!error.value) {
isCurrentSessionFeedbackRequested.value = true;
}
}; };
</script> </script>
@ -97,7 +79,7 @@ const onRequestFeedback = async () => {
/> />
<FeedbackRequestedInformationPanel <FeedbackRequestedInformationPanel
v-if="currentVisualState == VisualState.HAS_REQUESTED_FEEDBACK" v-if="currentVisualState == VisualState.HAS_REQUESTED_FEEDBACK"
:feedback-mentor-name="feedbackMentorName" :feedback-mentor-name="`${feedbackProvider?.first_name} ${feedbackProvider?.last_name}`"
/> />
<div v-else-if="currentVisualState == VisualState.HAS_NOT_REQUESTED_FEEDBACK"> <div v-else-if="currentVisualState == VisualState.HAS_NOT_REQUESTED_FEEDBACK">
<p> <p>
@ -107,20 +89,11 @@ const onRequestFeedback = async () => {
) )
}} }}
</p> </p>
<select <ItDropdownSelect
v-model="currentSessionRequestedMentor" v-model="currentSessionRequestedMentor"
data-cy="select-learning-mentor" class="mt-6 w-80"
class="mt-6" :items="mentors"
> ></ItDropdownSelect>
<option
v-for="learningMentor in mentors"
:key="learningMentor.id"
:value="learningMentor.mentor"
>
{{ learningMentor.mentor.first_name }}
{{ learningMentor.mentor.last_name }}
</option>
</select>
<ItButton <ItButton
class="mt-6" class="mt-6"
variant="primary" variant="primary"
@ -134,7 +107,7 @@ const onRequestFeedback = async () => {
<p v-else> <p v-else>
{{ {{
$t("a.Selbsteinschätzung mit MENTOR_NAME teilen", { $t("a.Selbsteinschätzung mit MENTOR_NAME teilen", {
MENTOR_NAME: feedbackMentorName, MENTOR_NAME: currentSessionRequestedMentor?.name,
}) })
}} }}
</p> </p>

View File

@ -1,5 +1,6 @@
import { useCSRFFetch } from "@/fetchHelpers"; import { useCSRFFetch } from "@/fetchHelpers";
import type { User } from "@/types"; import type { User } from "@/types";
import { toValue } from "@vueuse/core";
import { t } from "i18next"; import { t } from "i18next";
import type { Ref } from "vue"; import type { Ref } from "vue";
import { computed, onMounted, ref } from "vue"; import { computed, onMounted, ref } from "vue";
@ -26,6 +27,9 @@ export interface Criterion {
/** To keep the backend permissions model simple, we have two endpoints: /** To keep the backend permissions model simple, we have two endpoints:
* 1. /requester/: for the user who requested the feedback * 1. /requester/: for the user who requested the feedback
* 2. /provider/: for the user who provides the feedback * 2. /provider/: for the user who provides the feedback
*
* Design decision: We generally just re-fetch the whole feedback from the backend
* after each action (e.g. request, release, add-assessment) to keep the frontend simple.
*/ */
export function useSelfEvaluationFeedback( export function useSelfEvaluationFeedback(
learningUnitId: Ref<string> | string, learningUnitId: Ref<string> | string,
@ -42,6 +46,8 @@ export function useSelfEvaluationFeedback(
const fetch = async () => { const fetch = async () => {
error.value = undefined; error.value = undefined;
loading.value = true; loading.value = true;
console.log("Fetching feedback for learning unit", learningUnitId);
const { data, statusCode, error: _error } = await useCSRFFetch(url.value).json(); const { data, statusCode, error: _error } = await useCSRFFetch(url.value).json();
loading.value = false; loading.value = false;
@ -58,6 +64,22 @@ export function useSelfEvaluationFeedback(
} }
}; };
const requestFeedback = async (fromProviderUserId: string) => {
if (feedbackRole !== "requester") {
console.warn("Cannot request feedback");
return;
}
const url = `/api/self-evaluation-feedback/requester/${toValue(
learningUnitId
)}/feedback/start`;
await useCSRFFetch(url).post({
feedback_provider_user_id: fromProviderUserId,
});
await fetch();
};
const addFeedbackAssessment = async ( const addFeedbackAssessment = async (
courseCompletionId: string, courseCompletionId: string,
assessment: "FAIL" | "SUCCESS" assessment: "FAIL" | "SUCCESS"
@ -74,8 +96,6 @@ export function useSelfEvaluationFeedback(
feedback_assessment: assessment, feedback_assessment: assessment,
}); });
// KISS: the backend is our "store" so just
// re-fetch e whole feedback from the backend
await fetch(); await fetch();
}; };
@ -89,8 +109,6 @@ export function useSelfEvaluationFeedback(
`/api/self-evaluation-feedback/provider/feedback/${feedback.value.feedback_id}/release` `/api/self-evaluation-feedback/provider/feedback/${feedback.value.feedback_id}/release`
).put({}); ).put({});
// KISS: the backend is our "store" so just
// re-fetch e whole feedback from the backend
await fetch(); await fetch();
}; };
@ -100,6 +118,8 @@ export function useSelfEvaluationFeedback(
feedback, feedback,
error, error,
loading, loading,
// feedback requester actions
requestFeedback,
// feedback provider actions // feedback provider actions
addFeedbackAssessment, addFeedbackAssessment,
releaseFeedback, releaseFeedback,