124 lines
3.5 KiB
Vue
124 lines
3.5 KiB
Vue
<script setup lang="ts">
|
|
import ItTextarea from "@/components/ui/ItTextarea.vue";
|
|
import { useAssignmentStore } from "@/stores/assignmentStore";
|
|
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
|
import type {
|
|
Assignment,
|
|
AssignmentCompletionData,
|
|
CourseSessionUser,
|
|
ExpertData,
|
|
} from "@/types";
|
|
import { useDebounceFn } from "@vueuse/core";
|
|
import * as log from "loglevel";
|
|
import { computed } from "vue";
|
|
|
|
const props = defineProps<{
|
|
assignmentUser: CourseSessionUser;
|
|
assignment: Assignment;
|
|
taskIndex: number;
|
|
}>();
|
|
|
|
log.debug("EvaluationTask setup", props.taskIndex);
|
|
|
|
const courseSessionStore = useCourseSessionsStore();
|
|
const assignmentStore = useAssignmentStore();
|
|
|
|
const task = computed(() => props.assignment.evaluation_tasks[props.taskIndex]);
|
|
|
|
const expertData = computed(() => {
|
|
const data = (assignmentStore.assignmentCompletion?.completion_data?.[task.value.id]
|
|
?.expert_data ?? {
|
|
points: 0,
|
|
text: "",
|
|
}) as ExpertData;
|
|
return data;
|
|
});
|
|
|
|
function changePoints(points: number) {
|
|
log.debug("changePoints", points);
|
|
evaluateAssignmentCompletion({
|
|
[task.value.id]: {
|
|
expert_data: { points, text: expertData.value.text },
|
|
},
|
|
});
|
|
}
|
|
function onUpdateText(value: string) {
|
|
// log.debug("onUpdateText", value);
|
|
evaluateAssignmentCompletionDebounced({
|
|
[task.value.id]: {
|
|
expert_data: {
|
|
text: value,
|
|
points: expertData.value.points,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
async function evaluateAssignmentCompletion(completionData: AssignmentCompletionData) {
|
|
log.debug("evaluateAssignmentCompletion", completionData);
|
|
|
|
return assignmentStore.evaluateAssignmentCompletion({
|
|
assignment_user_id: Number(props.assignmentUser.user_id),
|
|
assignment_id: props.assignment.id,
|
|
course_session_id: courseSessionStore.currentCourseSession!.id,
|
|
completion_data: completionData,
|
|
completion_status: "evaluation_in_progress",
|
|
});
|
|
}
|
|
|
|
const evaluateAssignmentCompletionDebounced = useDebounceFn(
|
|
evaluateAssignmentCompletion,
|
|
300
|
|
);
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<div class="text-bold mb-4 text-sm">
|
|
Beurteilungskriterium {{ taskIndex + 1 }} /
|
|
{{ props.assignment.evaluation_tasks.length }}
|
|
{{ task.value.title }}
|
|
</div>
|
|
|
|
<h3 class="default-wagtail-rich-text mb-8" v-html="task.value.description"></h3>
|
|
|
|
<fieldset>
|
|
<div>
|
|
<div
|
|
v-for="(subTask, index) in task.value.sub_tasks"
|
|
:key="index"
|
|
class="mb-4 flex items-center last:mb-0"
|
|
>
|
|
<input
|
|
:id="String(index)"
|
|
name="coursesessions"
|
|
type="radio"
|
|
:value="subTask.points"
|
|
:checked="expertData.points === subTask.points"
|
|
class="focus:ring-indigo-900 h-4 w-4 border-gray-300 text-blue-900"
|
|
@change="changePoints(subTask.points)"
|
|
/>
|
|
<label :for="String(index)" class="ml-4 block">
|
|
<div>{{ subTask.title }}</div>
|
|
<div
|
|
v-if="subTask.description"
|
|
class="default-wagtail-rich-text"
|
|
v-html="subTask.description"
|
|
></div>
|
|
<div class="text-sm text-gray-800">{{ subTask.points }} Punkte</div>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
<ItTextarea
|
|
class="mt-8"
|
|
:model-value="expertData.text ?? ''"
|
|
label="Begründung"
|
|
placeholder="Hier muss zwingend eine Begründung erfasst werden."
|
|
@update:model-value="onUpdateText($event)"
|
|
></ItTextarea>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped></style>
|