diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 643ff17db9651a866c10dedddd59f1feb9d6f84f..5389b8747a7f76495756ad47fda11d9e410319cf 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -9,6 +9,12 @@ and this project adheres to `Semantic Versioning`_.
 Unreleased
 ----------
 
+Added
+~~~~~
+
+* New timetable interface based on calendar system.
+* [Dev] LessonEvent and SupervisionEvent basing on calendar system.
+
 `3.0.2`_ - 2023-09-10
 ---------------------
 
diff --git a/aleksis/apps/chronos/frontend/components/AmendLesson.vue b/aleksis/apps/chronos/frontend/components/AmendLesson.vue
index 5219ca94448c3bef3995827a6e957bd849b71083..1d6ac1fadd0570fdf85aeb429bebc0ed3a210e6c 100644
--- a/aleksis/apps/chronos/frontend/components/AmendLesson.vue
+++ b/aleksis/apps/chronos/frontend/components/AmendLesson.vue
@@ -13,17 +13,18 @@
       v-model="edit"
       :fields="fields"
       :is-create="!selectedEvent.meta.amended"
-      createItemI18nKey="chronos.event.amend.title"
+      create-item-i18n-key="chronos.event.amend.title"
       :gql-create-mutation="gqlCreateMutation"
       :get-create-data="transformCreateData"
       :default-item="defaultItem"
-      editItemI18nKey="chronos.event.amend.title"
+      edit-item-i18n-key="chronos.event.amend.title"
       :gql-patch-mutation="gqlPatchMutation"
       :get-patch-data="transformPatchData"
       :edit-item="initPatchData"
       @cancel="open = false"
       @save="updateOnSave()"
     >
+      <!-- eslint-disable-next-line vue/valid-v-slot -->
       <template #subject.field="{ attrs, on, item }">
         <v-autocomplete
           :disabled="item.cancelled"
@@ -34,6 +35,7 @@
           v-on="on"
         />
       </template>
+      <!-- eslint-disable-next-line vue/valid-v-slot -->
       <template #teachers.field="{ attrs, on, item }">
         <v-autocomplete
           :disabled="item.cancelled"
@@ -47,6 +49,7 @@
           deletable-chips
         />
       </template>
+      <!-- eslint-disable-next-line vue/valid-v-slot -->
       <template #rooms.field="{ attrs, on, item }">
         <v-autocomplete
           :disabled="item.cancelled"
@@ -60,20 +63,22 @@
           deletable-chips
         />
       </template>
+      <!-- eslint-disable-next-line vue/valid-v-slot -->
       <template #cancelled.field="{ attrs, on }">
         <v-checkbox v-bind="attrs" v-on="on" />
       </template>
+      <!-- eslint-disable-next-line vue/valid-v-slot -->
       <template #comment.field="{ attrs, on }">
         <v-textarea v-bind="attrs" v-on="on" />
       </template>
     </dialog-object-form>
     <delete-dialog
-      deleteSuccessMessageI18nKey="chronos.event.amend.delete_success"
+      delete-success-message-i18n-key="chronos.event.amend.delete_success"
       :gql-delete-mutation="gqlDeleteMutation"
       v-model="deleteEvent"
       :items="[selectedEvent.meta]"
       @save="updateOnSave()"
-      >
+    >
       <template #title>
         {{ $t("chronos.event.amend.delete_dialog") }}
       </template>
diff --git a/aleksis/apps/chronos/managers.py b/aleksis/apps/chronos/managers.py
index adc91d148d9b72723ccd37d52e411e7859858055..72b9a30645eebbeba469f33fa886143b3370bde0 100644
--- a/aleksis/apps/chronos/managers.py
+++ b/aleksis/apps/chronos/managers.py
@@ -927,13 +927,27 @@ class LessonEventQuerySet(PolymorphicQuerySet):
         )
 
     def related_to_person(self, person: Union[int, Person]) -> "LessonEventQuerySet":
-        """Get all lesson events related to a certain person (as teacher/participant/group owner/parent group owner, including amends)."""
+        """Get all lesson events a certain person is allowed to see.
+
+        This includes all lesson events the person is assigned to as
+        teacher/participant/group owner/parent group owner,
+        including those amended.
+        """
         amended = self.filter(
             Q(amended_by__isnull=False)
-            & (Q(teachers=person) | Q(groups__members=person) | Q(groups__owners=person) | Q(groups__parent_groups__owners=person))
+            & (
+                Q(teachers=person)
+                | Q(groups__members=person)
+                | Q(groups__owners=person)
+                | Q(groups__parent_groups__owners=person)
+            )
         ).values_list("amended_by__pk", flat=True)
         return self.filter(
-            Q(teachers=person) | Q(groups__members=person) | Q(groups__owners=person) | Q(groups__parent_groups__owners=person) | Q(pk__in=amended)
+            Q(teachers=person)
+            | Q(groups__members=person)
+            | Q(groups__owners=person)
+            | Q(groups__parent_groups__owners=person)
+            | Q(pk__in=amended)
         ).distinct()
 
     def not_amended(self) -> "LessonEventQuerySet":
diff --git a/aleksis/apps/chronos/models.py b/aleksis/apps/chronos/models.py
index 1711856a1998ceaba3c6831b9bd094dc20521a1a..862e719cc2f7583cd173407f270c0b7141f41651 100644
--- a/aleksis/apps/chronos/models.py
+++ b/aleksis/apps/chronos/models.py
@@ -1437,7 +1437,7 @@ class LessonEvent(CalendarEvent):
     def subject_name_with_amends(self: LessonEvent) -> str:
         """Get formatted subject name (including amends)."""
         my_subject = self.subject.name if self.subject else ""
-        amended_subject = self.amends.subject.name if self.amends else ""
+        amended_subject = self.amends.subject.name if self.amends and self.amends.subject else ""
 
         if my_subject and amended_subject:
             return _("{} (instead of {})").format(my_subject, amended_subject)
@@ -1452,15 +1452,19 @@ class LessonEvent(CalendarEvent):
         """Get the title of the lesson event."""
         if reference_object.title:
             return reference_object.title
-        elif reference_object.subject:
-            title = reference_object.subject.name
+        elif reference_object.subject or (
+            reference_object.amends and reference_object.amends.subject
+        ):
+            title = reference_object.subject_name_with_amends
             if request and request.user.person in reference_object.teachers.all():
                 title += " · " + reference_object.group_names
             elif request:
-                title += " · " + reference_object.teacher_names
+                title += " · " + reference_object.teacher_names_with_amends
             else:
-                title += f" · {reference_object.group_names} · {reference_object.teacher_names}"
-
+                title += (
+                    f" · {reference_object.group_names} · "
+                    + f"{reference_object.teacher_names_with_amends}"
+                )
             if reference_object.rooms.all().exists():
                 title += " · " + reference_object.room_names_with_amends
             return title
diff --git a/aleksis/apps/chronos/schema/__init__.py b/aleksis/apps/chronos/schema/__init__.py
index 2aebe36ef9ec9ac6e1d1e3c5b3963270e6b7a3a2..9c9861ad173dbcd597d2356596b32ae763690750 100644
--- a/aleksis/apps/chronos/schema/__init__.py
+++ b/aleksis/apps/chronos/schema/__init__.py
@@ -7,7 +7,11 @@ from django.db.models import F, ManyToManyField, OuterRef, Subquery, Q, Prefetch
 
 import graphene
 from graphene_django import DjangoObjectType
-from graphene_django_cud.mutations import DjangoBatchCreateMutation, DjangoBatchDeleteMutation, DjangoBatchPatchMutation
+from graphene_django_cud.mutations import (
+    DjangoBatchCreateMutation,
+    DjangoBatchDeleteMutation,
+    DjangoBatchPatchMutation,
+)
 
 from aleksis.core.models import CalendarEvent, Group, Person, Room
 from aleksis.core.schema.base import DeleteMutation, FilterOrderList
@@ -106,7 +110,7 @@ class AmendLessonBatchCreateMutation(DatetimeTimezoneMixin, DjangoBatchCreateMut
         )
 
     @classmethod
-    def before_save(cls, root, info, input, created_objects):
+    def before_save(cls, root, info, input, created_objects):  # noqa: A002
         for obj in created_objects:
             obj.timezone = obj.amends.timezone
         return created_objects
@@ -119,7 +123,7 @@ class AmendLessonBatchPatchMutation(DatetimeTimezoneMixin, DjangoBatchPatchMutat
         only_fields = ("id", "subject", "teachers", "groups", "rooms", "cancelled", "comment")
 
     @classmethod
-    def before_save(cls, root, info, input, updated_objects):
+    def before_save(cls, root, info, input, updated_objects):  # noqa: A002
         for obj in updated_objects:
             obj.timezone = obj.amends.timezone
         return updated_objects