Filter appointments by course
This commit is contained in:
parent
6048129507
commit
a180c5c825
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
})
|
});
|
||||||
|
});
|
||||||
})
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue