diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/PersonalNotes.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/PersonalNotes.vue
index 0487e70841c81d2bc3be5258b257c39c1c540833..2a3d953f03484ef2af2f1ac7a8f876bcb658f8bf 100644
--- a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/PersonalNotes.vue
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/PersonalNotes.vue
@@ -1,7 +1,6 @@
 <script setup>
-import SecondaryActionButton from "aleksis.core/components/generic/buttons/SecondaryActionButton.vue";
 import ExtraMarksNote from "./ExtraMarksNote.vue";
-import NoteNote from "./NoteNote.vue";
+import TextNotes from "./TextNotes.vue";
 </script>
 <script>
 import personalNoteRelatedMixin from "./personalNoteRelatedMixin";
@@ -14,6 +13,10 @@ export default {
 
 <template>
   <div>
+    <text-notes
+      v-bind="personalNoteRelatedProps"
+      :value="participation.notesWithNote"
+    />
 
     <extra-marks-note
       v-bind="personalNoteRelatedProps"
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNote.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNote.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d5f35b553e32cadb8c7e8c2ac61d712f440770a6
--- /dev/null
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNote.vue
@@ -0,0 +1,92 @@
+<script>
+import {
+  createPersonalNotes,
+  updatePersonalNotes,
+} from "./personal_notes.graphql";
+import personalNoteRelatedMixin from "./personalNoteRelatedMixin";
+import mutateMixin from "aleksis.core/mixins/mutateMixin.js";
+
+export default {
+  name: "TextNote",
+  mixins: [mutateMixin, personalNoteRelatedMixin],
+  props: {
+    value: {
+      type: Object,
+      required: true,
+    },
+  },
+  computed: {
+    model: {
+      get() {
+        return this.value.note;
+      },
+      set(newValue) {
+        const input = (extras) => ({
+          input: [
+            {
+              note: newValue,
+              ...extras,
+            },
+          ],
+        });
+
+        const updater =
+          (replace) => (storedDocumentations, incomingPersonalNotes) => {
+            const note = incomingPersonalNotes[0];
+            const documentation = storedDocumentations.find(
+              (doc) => doc.id === this.documentation.id,
+            );
+            const participationStatus = documentation.participations.find(
+              (part) => part.id === this.participation.id,
+            );
+            if (replace) {
+              const index = participationStatus.notesWithNote.findIndex(
+                (n) => n.id === this.participation.id,
+              );
+              participationStatus.notesWithNote.splice(index, 1, note);
+            } else {
+              participationStatus.notesWithNote.push(note);
+
+              this.$emit("create");
+            }
+
+            return storedDocumentations;
+          };
+
+        const create = !this.value.id;
+
+        this.mutate(
+          create ? createPersonalNotes : updatePersonalNotes,
+          input(
+            create
+              ? {
+                  documentation: this.documentation.id,
+                  person: this.participation.person.id,
+                  extraMark: null,
+                }
+              : {
+                  id: this.value.id,
+                },
+          ),
+          updater(!create),
+        );
+      },
+    },
+  },
+};
+</script>
+
+<template>
+  <v-textarea
+    auto-grow
+    :rows="3"
+    outlined
+    hide-details
+    class="mb-4"
+    clearable
+    :label="$t('alsijil.personal_notes.note')"
+    :value="model"
+    @change="model = $event"
+    :loading="loading"
+  />
+</template>
diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNotes.vue b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNotes.vue
new file mode 100644
index 0000000000000000000000000000000000000000..dd32164db251b16acdc8b61daa29559b9a776fde
--- /dev/null
+++ b/aleksis/apps/alsijil/frontend/components/coursebook/personal_notes/TextNotes.vue
@@ -0,0 +1,48 @@
+<script setup>
+import SecondaryActionButton from "aleksis.core/components/generic/buttons/SecondaryActionButton.vue";
+import TextNote from "./TextNote.vue";
+</script>
+<script>
+import personalNoteRelatedMixin from "./personalNoteRelatedMixin";
+
+export default {
+  name: "TextNotes",
+  mixins: [personalNoteRelatedMixin],
+  props: {
+    value: {
+      type: Array,
+      required: true,
+    },
+  },
+  data() {
+    return {
+      showNewNote: true,
+    };
+  },
+  computed: {
+    notes() {
+      return this.showNewNote ? [...this.value, { note: "" }] : this.value;
+    },
+  },
+};
+</script>
+
+<template>
+  <div>
+    <text-note
+      v-for="note in notes"
+      :key="note.id || -1"
+      v-bind="personalNoteRelatedProps"
+      :value="note"
+      @create="showNewNote = false"
+    />
+
+    <secondary-action-button
+      i18n-key="alsijil.personal_notes.create_personal_note"
+      icon-text="$plus"
+      class="full-width"
+      @click="showNewNote = true"
+      :disabled="showNewNote"
+    />
+  </div>
+</template>