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

View File

@ -1,5 +1,6 @@
import { useCSRFFetch } from "@/fetchHelpers";
import type { User } from "@/types";
import { toValue } from "@vueuse/core";
import { t } from "i18next";
import type { 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:
* 1. /requester/: for the user who requested 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(
learningUnitId: Ref<string> | string,
@ -42,6 +46,8 @@ export function useSelfEvaluationFeedback(
const fetch = async () => {
error.value = undefined;
loading.value = true;
console.log("Fetching feedback for learning unit", learningUnitId);
const { data, statusCode, error: _error } = await useCSRFFetch(url.value).json();
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 (
courseCompletionId: string,
assessment: "FAIL" | "SUCCESS"
@ -74,8 +96,6 @@ export function useSelfEvaluationFeedback(
feedback_assessment: assessment,
});
// KISS: the backend is our "store" so just
// re-fetch e whole feedback from the backend
await fetch();
};
@ -89,8 +109,6 @@ export function useSelfEvaluationFeedback(
`/api/self-evaluation-feedback/provider/feedback/${feedback.value.feedback_id}/release`
).put({});
// KISS: the backend is our "store" so just
// re-fetch e whole feedback from the backend
await fetch();
};
@ -100,6 +118,8 @@ export function useSelfEvaluationFeedback(
feedback,
error,
loading,
// feedback requester actions
requestFeedback,
// feedback provider actions
addFeedbackAssessment,
releaseFeedback,