diff --git a/js/src/graphql/event.ts b/js/src/graphql/event.ts
index a3be313ff..b5989eeb0 100644
--- a/js/src/graphql/event.ts
+++ b/js/src/graphql/event.ts
@@ -1,134 +1,157 @@
 import gql from 'graphql-tag';
 
+const participantQuery = `
+  role,
+  actor {
+    preferredUsername,
+    avatarUrl,
+    name
+  }
+`;
+
 export const FETCH_EVENT = gql`
-    query($uuid:UUID!) {
-        event(uuid: $uuid) {
-            id,
-            uuid,
-            url,
-            local,
-            title,
-            description,
-            beginsOn,
-            endsOn,
-            status,
-            visibility,
-            thumbnail,
-            large_image,
-            publish_at,
-            # online_address,
-            # phone_address,
-            organizerActor {
-                avatarUrl,
-                preferredUsername,
-                name,
-            },
-            # attributedTo {
-            #     # avatarUrl,
-            #     preferredUsername,
-            #     name,
-            # },
-            participants {
-                actor {
-                    avatarUrl,
-                    preferredUsername,
-                    name,
-                },
-                role,
-            },
-            category {
-                title,
-            },
-        }
-        }
+  query($uuid:UUID!) {
+    event(uuid: $uuid) {
+      id,
+      uuid,
+      url,
+      local,
+      title,
+      description,
+      beginsOn,
+      endsOn,
+      status,
+      visibility,
+      thumbnail,
+      large_image,
+      publish_at,
+      # online_address,
+      # phone_address,
+      organizerActor {
+        avatarUrl,
+        preferredUsername,
+        name,
+      },
+      # attributedTo {
+      #     # avatarUrl,
+      #     preferredUsername,
+      #     name,
+      # },
+      participants {
+        ${participantQuery}
+      },
+      category {
+        title,
+      },
+    }
+  }
 `;
 
 export const FETCH_EVENTS = gql`
-    query {
-        events {
-        id,
-        uuid,
-        url,
-        local,
+  query {
+    events {
+      id,
+      uuid,
+      url,
+      local,
+      title,
+      description,
+      beginsOn,
+      endsOn,
+      status,
+      visibility,
+      thumbnail,
+      large_image,
+      publish_at,
+      # online_address,
+      # phone_address,
+      organizerActor {
+        avatarUrl,
+        preferredUsername,
+        name,
+      },
+      attributedTo {
+        avatarUrl,
+        preferredUsername,
+        name,
+      },
+      category {
         title,
-        description,
-        beginsOn,
-        endsOn,
-        status,
-        visibility,
-        thumbnail,
-        large_image,
-        publish_at,
-        # online_address,
-        # phone_address,
-        organizerActor {
-            avatarUrl,
-            preferredUsername,
-            name,
-        },
-        attributedTo {
-            avatarUrl,
-            preferredUsername,
-            name,
-        },
-        category {
-            title,
-        },
-        participants {
-            role,
-            actor {
-                preferredUsername,
-                avatarUrl,
-                name
-            }
-        }
+      },
+      participants {
+        ${participantQuery}
+      }
     }
-}
+  }
 `;
 
 export const CREATE_EVENT = gql`
-    mutation CreateEvent(
-        $title: String!,
-        $description: String!,
-        $organizerActorId: String!,
-        $category: String!,
-        $beginsOn: DateTime!
+  mutation CreateEvent(
+  $title: String!,
+  $description: String!,
+  $organizerActorId: String!,
+  $category: String!,
+  $beginsOn: DateTime!
+  ) {
+    createEvent(
+      title: $title,
+      description: $description,
+      beginsOn: $beginsOn,
+      organizerActorId: $organizerActorId,
+      category: $category
     ) {
-        createEvent(
-            title: $title,
-            description: $description,
-            beginsOn: $beginsOn,
-            organizerActorId: $organizerActorId,
-            category: $category
-        ) {
-            id,
-            uuid,
-            title
-        }
-}
+      id,
+      uuid,
+      title
+    }
+  }
 `;
 
 export const EDIT_EVENT = gql`
-    mutation EditEvent(
-        $title: String!,
-        $description: String!,
-        $organizerActorId: Int!,
-        $categoryId: Int!
-        ) {
+  mutation EditEvent(
+  $title: String!,
+  $description: String!,
+  $organizerActorId: Int!,
+  $categoryId: Int!
+  ) {
     EditEvent(title: $title, description: $description, organizerActorId: $organizerActorId, categoryId: $categoryId) {
-    uuid
+      uuid
     }
-}
+  }
 `;
 
 export const JOIN_EVENT = gql`
-    mutation JoinEvent(
-        $uuid: String!,
-        $username: String!    
+  mutation JoinEvent($id: Int!, $actorId: Int!) {
+    joinEvent(
+      id: $id,
+      actorId: $actorId
     ) {
-        joinEvent(
-            uuid: $uuid,
-            username: $username
-        )
-}
+      actor {
+        ${participantQuery}
+      },
+      role
+    }
+  }
+`;
+
+export const LEAVE_EVENT = gql`
+  mutation LeaveEvent($id: Int!, $actorId: Int!) {
+    leaveEvent(
+      id: $id,
+      actorId: $actorId
+    ) {
+      actor {
+        id
+      }
+    }
+  }
+`;
+
+export const DELETE_EVENT = gql`
+  mutation DeleteEvent($id: Int!, $actorId: Int!) {
+    deleteEvent(
+      id: $id,
+      actorId: $actorId
+    )
+  }
 `;
diff --git a/js/src/router/user.ts b/js/src/router/user.ts
index 811723730..24bb0b98e 100644
--- a/js/src/router/user.ts
+++ b/js/src/router/user.ts
@@ -7,54 +7,54 @@ import SendPasswordReset from '@/views/User/SendPasswordReset.vue';
 import PasswordReset from '@/views/User/PasswordReset.vue';
 
 export default [
-    {
-        path: '/register/user',
-        name: 'Register',
-        component: RegisterUser,
-        props: true,
-        meta: { requiredAuth: false },
-    },
-    {
-        path: '/register/profile',
-        name: 'RegisterProfile',
-        component: RegisterProfile,
-        props: true,
-        meta: { requiredAuth: false },
-    },
-    {
-        path: '/resend-instructions',
-        name: 'ResendConfirmation',
-        component: ResendConfirmation,
-        props: true,
-        meta: { requiresAuth: false },
-    },
-    {
-        path: '/password-reset/send',
-        name: 'SendPasswordReset',
-        component: SendPasswordReset,
-        props: true,
-        meta: { requiresAuth: false },
-    },
-    {
-        path: '/password-reset/:token',
-        name: 'PasswordReset',
-        component: PasswordReset,
-        meta: { requiresAuth: false },
-        props: true,
-    },
-    {
-        path: '/validate/:token',
-        name: 'Validate',
-        component: Validate,
-        // We can only pass string values through params, therefore
-        props: (route) => ({ email: route.params.email, userAlreadyActivated: route.params.userAlreadyActivated === 'true'}),
-        meta: { requiresAuth: false },
-    },
-    {
-        path: '/login',
-        name: 'Login',
-        component: Login,
-        props: true,
-        meta: { requiredAuth: false },
-    },
-];
\ No newline at end of file
+  {
+    path: '/register/user',
+    name: 'Register',
+    component: RegisterUser,
+    props: true,
+    meta: { requiredAuth: false },
+  },
+  {
+    path: '/register/profile',
+    name: 'RegisterProfile',
+    component: RegisterProfile,
+    props: true,
+    meta: { requiredAuth: false },
+  },
+  {
+    path: '/resend-instructions',
+    name: 'ResendConfirmation',
+    component: ResendConfirmation,
+    props: true,
+    meta: { requiresAuth: false },
+  },
+  {
+    path: '/password-reset/send',
+    name: 'SendPasswordReset',
+    component: SendPasswordReset,
+    props: true,
+    meta: { requiresAuth: false },
+  },
+  {
+    path: '/password-reset/:token',
+    name: 'PasswordReset',
+    component: PasswordReset,
+    meta: { requiresAuth: false },
+    props: true,
+  },
+  {
+    path: '/validate/:token',
+    name: 'Validate',
+    component: Validate,
+    // We can only pass string values through params, therefore
+    props: (route) => ({ email: route.params.email, userAlreadyActivated: route.params.userAlreadyActivated === 'true'}),
+    meta: { requiresAuth: false },
+  },
+  {
+    path: '/login',
+    name: 'Login',
+    component: Login,
+    props: true,
+    meta: { requiredAuth: false },
+  },
+];
diff --git a/js/src/types/actor.model.ts b/js/src/types/actor.model.ts
index a5803c0b2..215df38cb 100644
--- a/js/src/types/actor.model.ts
+++ b/js/src/types/actor.model.ts
@@ -1,13 +1,13 @@
 export interface IActor {
-    id: string;
-    url: string;
-    name: string;
-    domain: string|null;
-    summary: string;
-    preferredUsername: string;
-    suspended: boolean;
-    avatarUrl: string;
-    bannerUrl: string;
+  id: string;
+  url: string;
+  name: string;
+  domain: string|null;
+  summary: string;
+  preferredUsername: string;
+  suspended: boolean;
+  avatarUrl: string;
+  bannerUrl: string;
 }
 
 export interface IPerson extends IActor {
@@ -15,15 +15,18 @@ export interface IPerson extends IActor {
 }
 
 export interface IGroup extends IActor {
-    members: IMember[];
+  members: IMember[];
 }
 
 export enum MemberRole {
-    PENDING, MEMBER, MODERATOR, ADMIN
+  PENDING,
+  MEMBER,
+  MODERATOR,
+  ADMIN,
 }
 
 export interface IMember {
-    role: MemberRole;
-    parent: IGroup;
-    actor: IActor;
-}
\ No newline at end of file
+  role: MemberRole;
+  parent: IGroup;
+  actor: IActor;
+}
diff --git a/js/src/types/event.model.ts b/js/src/types/event.model.ts
index e985748f4..48c713d13 100644
--- a/js/src/types/event.model.ts
+++ b/js/src/types/event.model.ts
@@ -1,62 +1,70 @@
-import { IActor } from "./actor.model";
+import { IActor } from './actor.model';
 
 export enum EventStatus {
-    TENTATIVE,
-    CONFIRMED,
-    CANCELLED
+  TENTATIVE,
+  CONFIRMED,
+  CANCELLED,
 }
 
 export enum EventVisibility {
-    PUBLIC,
-    UNLISTED,
-    RESTRICTED,
-    PRIVATE
+  PUBLIC,
+  UNLISTED,
+  RESTRICTED,
+  PRIVATE,
 }
 
 export enum EventJoinOptions {
-    FREE,
-    RESTRICTED,
-    INVITE
+  FREE,
+  RESTRICTED,
+  INVITE,
 }
 
 export enum ParticipantRole {
-    NOT_APPROVED = 'not_approved',
-    PARTICIPANT = 'participant',
-    MODERATOR = 'moderator',
-    ADMINSTRATOR = 'administrator',
-    CREATOR = 'creator'
+  NOT_APPROVED = 'not_approved',
+  PARTICIPANT = 'participant',
+  MODERATOR = 'moderator',
+  ADMINISTRATOR = 'administrator',
+  CREATOR = 'creator',
 }
 
 export interface ICategory {
-    title: string;
-    description: string;
-    picture: string;
+  title: string;
+  description: string;
+  picture: string;
 }
 
 export interface IParticipant {
-    role: ParticipantRole,
-    actor: IActor,
-    event: IEvent
+  role: ParticipantRole;
+  actor: IActor;
+  event: IEvent;
 }
 
 export interface IEvent {
-    uuid: string;
-    url: string;
-    local: boolean;
-    title: string;
-    description: string;
-    begins_on: Date;
-    ends_on: Date;
-    status: EventStatus;
-    visibility: EventVisibility;
-    join_options: EventJoinOptions;
-    thumbnail: string;
-    large_image: string;
-    publish_at: Date;
-    // online_address: Adress;
-    // phone_address: string;
-    organizerActor: IActor;
-    attributedTo: IActor;
-    participants: IParticipant[];
-    category: ICategory;
-}
\ No newline at end of file
+  id?: number;
+  uuid: string;
+  url: string;
+  local: boolean;
+
+  title: string;
+  description: string;
+  category: ICategory;
+
+  begins_on: Date;
+  ends_on: Date;
+  publish_at: Date;
+
+  status: EventStatus;
+  visibility: EventVisibility;
+
+  join_options: EventJoinOptions;
+
+  thumbnail: string;
+  large_image: string;
+
+  organizerActor: IActor;
+  attributedTo: IActor;
+  participants: IParticipant[];
+
+  // online_address: Address;
+  // phone_address: string;
+}
diff --git a/js/src/views/Event/Event.vue b/js/src/views/Event/Event.vue
index d2854ae02..24a03639d 100644
--- a/js/src/views/Event/Event.vue
+++ b/js/src/views/Event/Event.vue
@@ -93,13 +93,15 @@
 </template>
 
 <script lang="ts">
-import { FETCH_EVENT } from "@/graphql/event";
-import { Component, Prop, Vue } from "vue-property-decorator";
-import VueMarkdown from "vue-markdown";
-import { LOGGED_PERSON } from "../../graphql/actor";
-import { IEvent } from "@/types/event.model";
-import { JOIN_EVENT } from "../../graphql/event";
-import { IPerson } from "@/types/actor.model";
+import { DELETE_EVENT, FETCH_EVENT, LEAVE_EVENT } from '@/graphql/event';
+import { Component, Prop, Vue } from 'vue-property-decorator';
+import { LOGGED_PERSON } from '@/graphql/actor';
+import { IEvent, IParticipant } from '@/types/event.model';
+import { JOIN_EVENT } from '@/graphql/event';
+import { IPerson } from '@/types/actor.model';
+
+// No typings for this component, so we use require
+const VueMarkdown = require('vue-markdown');
 
 @Component({
   components: {
@@ -126,31 +128,73 @@ export default class Event extends Vue {
   loggedPerson!: IPerson;
   validationSent: boolean = false;
 
-  deleteEvent() {
+  async deleteEvent() {
     const router = this.$router;
-    // FIXME: remove eventFetch
-    // eventFetch(`/events/${this.uuid}`, this.$store, { method: 'DELETE' })
-    //   .then(() => router.push({ name: 'EventList' }));
+
+    try {
+      await this.$apollo.mutate<IParticipant>({
+        mutation: DELETE_EVENT,
+        variables: {
+          id: this.event.id,
+          actorId: this.loggedPerson.id,
+        }
+      });
+
+      router.push({ name: 'EventList' })
+    } catch (error) {
+      console.error(error);
+    }
   }
 
   async joinEvent() {
     try {
-      this.validationSent = true;
-      await this.$apollo.mutate({
-        mutation: JOIN_EVENT
+      await this.$apollo.mutate<IParticipant>({
+        mutation: JOIN_EVENT,
+        variables: {
+          id: this.event.id,
+          actorId: this.loggedPerson.id,
+        },
+        update: (store, { data: { joinEvent } }) => {
+          const event = store.readQuery<IEvent>({ query: FETCH_EVENT });
+          if (event === null) {
+            console.error('Cannot update event participant cache, because of null value.')
+            return
+          }
+
+          event.participants = event.participants.concat([ joinEvent ]);
+
+          store.writeQuery({ query: FETCH_EVENT, data: event });
+        }
       });
     } catch (error) {
       console.error(error);
     }
   }
 
-  leaveEvent() {
-    // FIXME: remove eventFetch
-    // eventFetch(`/events/${this.uuid}/leave`, this.$store)
-    //   .then(response => response.json())
-    //   .then((data) => {
-    //     console.log(data);
-    //   });
+  async leaveEvent() {
+    try {
+      await this.$apollo.mutate<IParticipant>({
+        mutation: LEAVE_EVENT,
+        variables: {
+          id: this.event.id,
+          actorId: this.loggedPerson.id,
+        },
+        update: (store, { data: { leaveEvent } }) => {
+          const event = store.readQuery<IEvent>({ query: FETCH_EVENT });
+          if (event === null) {
+            console.error('Cannot update event participant cache, because of null value.');
+            return
+          }
+
+          event.participants = event.participants
+            .filter(p => p.actor.id !== leaveEvent.actor.id);
+
+          store.writeQuery({ query: FETCH_EVENT, data: event });
+        }
+      });
+    } catch (error) {
+      console.error(error);
+    }
   }
 
   downloadIcsEvent() {
@@ -169,28 +213,16 @@ export default class Event extends Vue {
   }
 
   actorIsParticipant() {
-    return (
-      (this.loggedPerson &&
-        this.event.participants
-          .map(participant => participant.actor.preferredUsername)
-          .includes(this.loggedPerson.preferredUsername)) ||
-      this.actorIsOrganizer()
-    );
+    if (this.actorIsOrganizer()) return true;
+
+    return this.loggedPerson &&
+      this.event.participants
+          .some(participant => participant.actor.id === this.loggedPerson.id);
   }
-  //
+
   actorIsOrganizer() {
-    return (
-      this.loggedPerson &&
-      this.loggedPerson.preferredUsername ===
-        this.event.organizerActor.preferredUsername
-    );
+    return this.loggedPerson &&
+      this.loggedPerson.id === this.event.organizerActor.id;
   }
 }
 </script>
-
-<!-- Add "scoped" attribute to limit CSS to this component only -->
-<style>
-.v-card__media__background {
-  filter: contrast(0.4);
-}
-</style>