fix: use ItDropdown, simplify UI state
This commit is contained in:
parent
b44db0d788
commit
5d510e0d04
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue