diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absence/AbsenceDialog.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absence/AbsenceDialog.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f4de6f18e8f84208baf4b1abf1e79b05550c27d2
--- /dev/null
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/absence/AbsenceDialog.vue
@@ -0,0 +1,69 @@
+<template>
+  <mobile-fullscreen-dialog v-model="popup">
+    <template #activator="activator">
+      <!-- button +? -->
+      <!-- -> popup = true -->
+    </template>
+    <template #title>
+      <!-- Abwesenheit/Entschuldigung erfassen --> 
+      <!-- Abwesenheit/Entschuldigung Zusammenfassung --> 
+    </template>
+    <template #content>
+    <absence-form v-if="form" />
+    <absence-summary v-else />
+    </template>
+    <template #actions>
+      <!-- secondary -->
+      <!-- TODO: Return to form on cancel? form=true -->
+      <cancel-button
+        @click="popup = false"
+        disabled="loading"
+      />
+      <!-- primary -->
+      <save-button
+        v-if="form"
+        i18n-key="actions.continue"
+        @click="form = false"
+        :loading="loading"
+      />
+      <save-button
+        v-if="form"
+        i18n-key="actions.confirm"
+        @click="confirm"
+        :loading="loading"
+      />
+    </template>
+  </mobile-fullscreen-dialog>
+</template>
+
+<script>
+import MobileFullscreenDialog from "aleksis.core/components/generic/dialogs/MobileFullscreenDialog.vue";
+import AbsenceForm from "./AbsenceForm.vue";
+import AbsenceSummary from "./AbsenceSummary.vue";
+import CancelButton from "aleksis.core/components/generic/buttons/CancelButton.vue";
+import SaveButton from "aleksis.core/components/generic/buttons/SaveButton.vue";
+
+export default {
+  name: "AbsenceDialog",
+  components: {
+    MobileFullscreenDialog,
+    AbsenceForm,
+    AbsenceSummary,
+    CancelButton,
+    SaveButton,
+  },
+  data() {
+    return {
+      popup: false,
+      form: true,
+      loading: false,
+    };
+  },
+  methods: {
+    confirm() {
+      // TODO: Send mutation (shown in absence-summary)
+      popup = false,
+    },
+  },
+};
+</script>
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absence/AbsenceForm.uv b/aleksis/apps/alsijil/frontend/components/coursebook/absence/AbsenceForm.uv
new file mode 100644
index 0000000000000000000000000000000000000000..82a532eb2ce58a49a5cd717e2dc84d1733631c0e
--- /dev/null
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/absence/AbsenceForm.uv
@@ -0,0 +1,49 @@
+<template>
+  <v-container>
+    <v-row>
+      <!-- persons -->
+    </v-row>
+    <v-row>
+      <!-- Start -->
+      <v-col
+        cols="12"
+        :sm="6"
+        >
+        <date-field
+          :value="value"
+          @input="$emit('input', $event)"
+          :label="$t('date_select.label')"
+          :disabled="loading"
+          />
+      </v-col>
+      <!-- End -->
+      <v-col
+        cols="12"
+        :sm="6"
+        >
+        <date-field
+          :value="value"
+          @input="$emit('input', $event)"
+          :label="$t('date_select.label')"
+          :disabled="loading"
+          />
+      </v-col>
+    </v-row>
+    <v-row>
+      <!-- comment -->
+    </v-row>
+    <v-row>
+      <!-- TODO: Component from Julian -->
+    </v-row>
+  </v-container>
+</template>
+
+<script>
+import DateField from "aleksis.core/components/generic/forms/DateField.vue";
+export default {
+  name: "AbsenceForm",
+  components: {
+    DateField,
+  },
+};
+</script>
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absence/AbsenceSummary.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absence/AbsenceSummary.vue
new file mode 100644
index 0000000000000000000000000000000000000000..645294d87251209b02c22e3bd5dbf5c54854308b
--- /dev/null
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/absence/AbsenceSummary.vue
@@ -0,0 +1,25 @@
+<template>
+  <!-- TODO: Hide header -->
+  <c-r-u-d-iterator
+    :gql-query=""
+    :gql-additional-query-args="FROM FORM"
+    :enable-create="false"
+    :enable-edit="false"
+    :elevated="false"
+    >
+    <template #default="{ items }">
+      <!-- expandable card per person -->
+    </template>
+  </c-r-u-d-iterator>
+</template>
+
+<script>
+import CRUDIterator from "aleksis.core/components/generic/CRUDIterator.vue";
+
+export default {
+  name: "AbsenceSummary",
+  components: {
+    CRUD-Iterator,
+  },
+};
+</script>