Filter appointments by course

This commit is contained in:
Daniel Egger 2023-10-04 17:39:04 +02:00
parent 6048129507
commit a180c5c825
3 changed files with 83 additions and 85 deletions

View File

@ -27,6 +27,7 @@ const dueDatesDisplayed = computed(() => {
<li <li
v-for="dueDate in dueDatesDisplayed" v-for="dueDate in dueDatesDisplayed"
:key="dueDate.id" :key="dueDate.id"
class="cy-single-due-date"
:class="{ 'first:border-t': props.showTopBorder, 'border-b': true }" :class="{ 'first:border-t': props.showTopBorder, 'border-b': true }"
> >
<DueDateSingle <DueDateSingle

View File

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref, watch } from "vue"; import { computed, onMounted, ref, watch } from "vue";
import { useCourseSessionsStore } from "@/stores/courseSessions"; import { useCourseSessionsStore } from "@/stores/courseSessions";
import { useLearningPathStore } from "@/stores/learningPath"; import { useLearningPathStore } from "@/stores/learningPath";
import { useTranslation } from "i18next-vue"; import { useTranslation } from "i18next-vue";
@ -18,74 +18,71 @@ type Item = {
name: string; name: string;
}; };
const courses: (Item & { slug: string })[] =
courseSessionsStore.uniqueCourseSessionsByCourse.map((cs) => ({
id: cs.course.id,
name: cs.course.title,
slug: cs.course.slug,
}));
const selectedCourse = ref<Item>(courses[0]);
const courseSessions = computed(() => {
return [
{
id: UNFILTERED,
name: t("a.AlleDurchführungen"),
},
...courseSessionsStore.allCourseSessions
.filter((cs) => cs.course.id === selectedCourse.value.id)
.map((cs) => ({ id: cs.id, name: cs.title })),
];
});
const selectedSession = ref<Item>(courseSessions.value[0]);
const initialItemCircle: Item = { const initialItemCircle: Item = {
id: UNFILTERED, id: UNFILTERED,
name: t("a.AlleCircle"), name: t("a.AlleCircle"),
}; };
const circles = ref<Item[]>([initialItemCircle]); const circles = ref<Item[]>([initialItemCircle]);
const courseSessions: Item[] = [
{
id: UNFILTERED,
name: t("a.AlleDurchführungen"),
},
...courseSessionsStore.allCourseSessions.map((cs) => ({ id: cs.id, name: cs.title })),
];
const selectedSession = ref<Item>(courseSessions[0]);
const selectedCircle = ref<Item>(circles.value[0]); const selectedCircle = ref<Item>(circles.value[0]);
if (courseSessionsStore.currentCourseSession) { async function loadCircleValues() {
selectedSession.value = {
id: courseSessionsStore.currentCourseSession.id,
name: courseSessionsStore.currentCourseSession.title,
};
}
watch(selectedSession, async () => {
// We don't have all circles for the unfiltered session,
// we fetch them from the learning path when the session changes
const isUnfiltered = selectedSession.value.id === UNFILTERED;
const courseSession = courseSessionsStore.allCourseSessions.find(
(item) => item.id === selectedSession.value.id
);
if (!courseSession || isUnfiltered) {
resetCircles();
return;
}
const data = await learningPathStore.loadLearningPath( const data = await learningPathStore.loadLearningPath(
`${courseSession.course.slug}-lp`, `${selectedCourse.value.slug}-lp`,
undefined, undefined,
false, false,
false false
); );
if (data) { if (data) {
updateCircles(data.circles); circles.value = [
initialItemCircle,
...data.circles.map((circle) => ({ id: circle.id, name: circle.title })),
];
} else { } else {
resetCircles(); circles.value = [initialItemCircle];
} }
selectedCircle.value = circles.value[0];
}
watch(selectedCourse, async () => {
selectedSession.value = courseSessions.value[0];
await loadCircleValues();
}); });
const resetCircles = () => { onMounted(async () => {
circles.value = [initialItemCircle]; await loadCircleValues();
selectedCircle.value = circles.value[0]; });
};
const updateCircles = (newCircles: { id: number; title: string }[]) => {
circles.value = [
initialItemCircle,
...newCircles.map((circle) => ({ id: circle.id, name: circle.title })),
];
selectedCircle.value = circles.value[0];
};
const appointments = computed(() => { const appointments = computed(() => {
return courseSessionsStore return courseSessionsStore
.allDueDates() .allDueDates()
.filter((dueDate) => isMatchingSession(dueDate) && isMatchingCircle(dueDate)); .filter(
(dueDate) =>
isMatchingCourse(dueDate) &&
isMatchingSession(dueDate) &&
isMatchingCircle(dueDate)
);
}); });
const isMatchingSession = (dueDate: DueDate) => const isMatchingSession = (dueDate: DueDate) =>
@ -96,6 +93,9 @@ const isMatchingCircle = (dueDate: DueDate) =>
selectedCircle.value.id === UNFILTERED || selectedCircle.value.id === UNFILTERED ||
dueDate.circle?.id === selectedCircle.value.id; dueDate.circle?.id === selectedCircle.value.id;
const isMatchingCourse = (dueDate: DueDate) =>
courseSessions.value.map((cs) => cs.id).includes(dueDate.course_session as number);
const numAppointmentsToShow = ref(7); const numAppointmentsToShow = ref(7);
const canLoadMore = computed(() => { const canLoadMore = computed(() => {
return numAppointmentsToShow.value < appointments.value.length; return numAppointmentsToShow.value < appointments.value.length;
@ -109,8 +109,15 @@ async function loadAdditionalAppointments() {
<template> <template>
<div class="bg-gray-200"> <div class="bg-gray-200">
<div class="container-large px-8 py-8"> <div class="container-large px-8 py-8">
<header class="mb-6"> <header class="mb-6 flex flex-col lg:flex-row lg:items-center lg:justify-between">
<h1>{{ $t("a.AlleTermine") }}</h1> <h1>{{ $t("a.AlleTermine") }}</h1>
<div>
<ItDropdownSelect
v-model="selectedCourse"
data-cy="appointments-course-select"
:items="courses"
></ItDropdownSelect>
</div>
</header> </header>
<main> <main>
<div class="flex flex-col space-y-2"> <div class="flex flex-col space-y-2">
@ -121,14 +128,12 @@ async function loadAdditionalAppointments() {
:items="courseSessions" :items="courseSessions"
borderless borderless
></ItDropdownSelect> ></ItDropdownSelect>
<template v-if="selectedSession.id !== UNFILTERED"> <ItDropdownSelect
<ItDropdownSelect v-model="selectedCircle"
v-model="selectedCircle" data-cy="appointments-circle-select"
data-cy="appointments-circle-select" :items="circles"
:items="circles" borderless
borderless ></ItDropdownSelect>
></ItDropdownSelect>
</template>
</div> </div>
<div class="bg-white px-5"> <div class="bg-white px-5">
<DueDatesList <DueDatesList

View File

@ -1,49 +1,41 @@
import {login} from "./helpers"; import { login } from "./helpers";
const CIRCLE_SELECT = '[data-cy=appointments-circle-select]'; // constants
const SESSION_SELECT = '[data-cy=appointments-session-select]'; const COURSE_SELECT = "[data-cy=appointments-course-select]";
const APPOINTMENTS = '[data-cy=appointments-list]'; const SESSION_SELECT = "[data-cy=appointments-session-select]";
const CIRCLE_SELECT = "[data-cy=appointments-circle-select]";
const APPOINTMENTS = "[data-cy=appointments-list]";
describe("appointments.cy.js", () => { describe("appointments.cy.js", () => {
beforeEach(() => { beforeEach(() => {
cy.manageCommand("cypress_reset"); cy.manageCommand("cypress_reset");
login("test-student2@example.com", "test"); login("test-student2@example.com", "test");
cy.visit("/course/test-lehrgang/appointments"); cy.visit("/course/test-lehrgang/appointments");
// Pre-Select Bern
cy.get(SESSION_SELECT).click();
cy.get(SESSION_SELECT).contains("Bern").click();
cy.get(SESSION_SELECT).should("contain", "Bern");
}); });
it("preselects the correct course session (Bern)", () => { it("preselects first course (Test Lehrgang)", () => {
cy.visit("/course/test-lehrgang/appointments"); cy.visit("/course/test-lehrgang/appointments");
cy.get(SESSION_SELECT).should("contain", "Bern"); cy.get(COURSE_SELECT).should("contain", "Test Lehrgang");
})
it("preselects NO course session (all)", () => {
cy.visit("/appointments");
cy.get(SESSION_SELECT).should("contain", "Alle"); cy.get(SESSION_SELECT).should("contain", "Alle");
}) cy.get(CIRCLE_SELECT).should("contain", "Alle");
cy.get(".cy-single-due-date").should("have.length", 4);
});
it("can filter by circle", () => { it("can filter by circle", () => {
// TODO: Fix this test (somehow the circle select is not working) cy.get(CIRCLE_SELECT).click();
// because it's loading on change of the session select? cy.get(CIRCLE_SELECT).contains("Fahrzeug").click();
// cy.get(CIRCLE_SELECT).click(); // THEN
// cy.get(CIRCLE_SELECT).contains("Fahrzeug").click(); cy.get(APPOINTMENTS).should("not.contain", "Keine Termine");
// });
// // THEN
// cy.get(APPOINTMENTS).should("not.contain", "Keine Termine");
})
it("can switch course session to Zurich", () => { it("can switch course session", () => {
cy.get(SESSION_SELECT).click(); cy.get(SESSION_SELECT).click();
cy.get(SESSION_SELECT).contains("Zürich").click(); cy.get(SESSION_SELECT).contains("Zürich").click();
cy.get(SESSION_SELECT).should("contain", "Zürich"); cy.get(SESSION_SELECT).should("contain", "Zürich");
// THEN // THEN
cy.get(APPOINTMENTS).should("contain", "Keine Termine"); cy.get(APPOINTMENTS).should("contain", "Keine Termine");
}) });
});
})