diff --git a/.gitignore b/.gitignore
index 403adbc1e527906a4aa59558cd582c20bcd1d738..247cd6166cca2da2e9aa9cdf1bdad6338f02b627 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,11 @@
 .DS_Store
 node_modules
 /dist
+coverage
 
 
 # local env files
+.env
 .env.local
 .env.*.local
 
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 89d533e50ec3edaf1b3916b80bebdb35ddf9eae8..64226ef4d8cfb17bd806c1510b3063d28b96f959 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -16,30 +16,41 @@
 stages:          # List of stages for jobs, and their order of execution
   - build
   - test
-  - deploy
 
-build-job:       # This job runs in the build stage, which runs first.
+image: node:16
+
+cache:
+  paths:
+    - node_modules/
+
+install_dependencies_job:       # This job runs in the build stage, which runs first.
   stage: build
-  script:
-    - echo "Compiling the code..."
-    - echo "Compile complete."
 
-unit-test-job:   # This job runs in the test stage.
-  stage: test    # It only starts when the job in the build stage completes successfully.
   script:
-    - echo "Running unit tests... This will take about 60 seconds."
-    - sleep 60
-    - echo "Code coverage is 90%"
+    - echo "Installing dependencies..."
+    - npm install
+    - echo "Dependencies installed."
+  artifacts:
+    paths:
+      - node_modules/
+
 
 lint-test-job:   # This job also runs in the test stage.
   stage: test    # It can run at the same time as unit-test-job (in parallel).
   script:
-    - echo "Linting code... This will take about 10 seconds."
-    - sleep 10
-    - echo "No lint issues found."
+    - echo "Linting the code..."
+    - npm run lint
+    - echo "Code-linting complete."
+  artifacts:
+    paths:
+      - node_modules/
 
-deploy-job:      # This job runs in the deploy stage.
-  stage: deploy  # It only runs when *both* jobs in the test stage complete successfully.
+unit-test-job:   # This job runs in the test stage.
+  stage: test    # It only starts when the job in the build stage completes successfully.
   script:
-    - echo "Deploying application..."
-    - echo "Application successfully deployed."
+    - echo "Running unit tests..."
+    - npm run test:unit -- --coverage
+    - echo "Unit tests complete."
+  artifacts:
+    paths:
+      - node_modules/
diff --git a/package-lock.json b/package-lock.json
index 6c90cbdf471980e235f8a00ec59d5448b42f5298..52e8f82391ad66170f4ffe771040b0cdab18290f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,13 +14,14 @@
         "axios": "^0.26.1",
         "core-js": "^3.8.3",
         "cssom": "^0.5.0",
+        "jwt-decode": "^3.1.2",
         "roboto-fontface": "*",
         "vue": "^3.2.13",
         "vue-router": "^4.0.3",
         "vuelidate": "^0.7.7",
         "vuex": "^4.0.0",
         "vuex-persistedstate": "^4.1.0",
-        "webfontloader": "^1.0.0"
+        "webfontloader": "^1.6.28"
       },
       "devDependencies": {
         "@babel/core": "^7.12.16",
@@ -40,6 +41,7 @@
         "eslint-plugin-prettier": "^4.0.0",
         "eslint-plugin-vue": "^8.0.3",
         "jest": "^27.0.5",
+        "jest-serializer-vue": "^2.0.2",
         "postcss": "^8.4.12",
         "prettier": "^2.4.1",
         "tailwindcss": "^3.0.24"
@@ -11056,6 +11058,11 @@
         "graceful-fs": "^4.1.6"
       }
     },
+    "node_modules/jwt-decode": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
+      "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
+    },
     "node_modules/kind-of": {
       "version": "3.2.2",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@@ -24449,6 +24456,11 @@
         "universalify": "^2.0.0"
       }
     },
+    "jwt-decode": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
+      "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
+    },
     "kind-of": {
       "version": "3.2.2",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
diff --git a/package.json b/package.json
index fe4e8182e70eaa9150b6c4bd6aa9e414408ee7a9..1a2ddb7600d61ce70a4bf73e48bccf3bfb399e50 100644
--- a/package.json
+++ b/package.json
@@ -15,13 +15,14 @@
     "axios": "^0.26.1",
     "core-js": "^3.8.3",
     "cssom": "^0.5.0",
+    "jwt-decode": "^3.1.2",
     "roboto-fontface": "*",
     "vue": "^3.2.13",
     "vue-router": "^4.0.3",
     "vuelidate": "^0.7.7",
     "vuex": "^4.0.0",
     "vuex-persistedstate": "^4.1.0",
-    "webfontloader": "^1.0.0"
+    "webfontloader": "^1.6.28"
   },
   "devDependencies": {
     "@babel/core": "^7.12.16",
@@ -41,6 +42,7 @@
     "eslint-plugin-prettier": "^4.0.0",
     "eslint-plugin-vue": "^8.0.3",
     "jest": "^27.0.5",
+    "jest-serializer-vue": "^2.0.2",
     "postcss": "^8.4.12",
     "prettier": "^2.4.1",
     "tailwindcss": "^3.0.24"
diff --git a/src/App.vue b/src/App.vue
index 5b76f23163ca815832df46238f55d797931d2c0c..98240aef8109abb6b658cd4d7c5cd21106cb354e 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,17 +1,3 @@
 <template>
-  <v-app>
-    <v-main>
-      <router-view />
-    </v-main>
-  </v-app>
+  <router-view />
 </template>
-
-<script>
-export default {
-  name: "App",
-
-  data: () => ({
-    //
-  }),
-};
-</script>
diff --git a/src/assets/defaultUserProfileImage.jpg b/src/assets/defaultUserProfileImage.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..18c8cd70555d36af38f2bf164b0a22740b14cf6b
Binary files /dev/null and b/src/assets/defaultUserProfileImage.jpg differ
diff --git a/src/assets/removeIcon.png b/src/assets/removeIcon.png
new file mode 100644
index 0000000000000000000000000000000000000000..3c66b2a75ff7d81fd33622bf13a903f838f114ee
Binary files /dev/null and b/src/assets/removeIcon.png differ
diff --git a/src/components/CreateNewGroup.vue b/src/components/CreateNewGroup.vue
new file mode 100644
index 0000000000000000000000000000000000000000..ceb5303249f9797e27e06fea8c189f9ab99a095f
--- /dev/null
+++ b/src/components/CreateNewGroup.vue
@@ -0,0 +1,306 @@
+<template>
+  <div class="m-6">
+    <!-- Component heading -->
+    <div class="flex justify-center mt-6">
+      <p class="text-4xl">Opprett Gruppe</p>
+    </div>
+
+    <!-- Radio boxes -->
+    <div class="mt-6">
+      <label
+        class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
+        id="radioBoxLabel"
+        >Synlighet</label
+      >
+      <div class="form-check">
+        <input
+          class="form-check-input appearance-none rounded-full h-4 w-4 border border-gray-300 bg-white checked:bg-blue-600 checked:border-blue-600 focus:outline-none transition duration-200 mt-1 align-top bg-no-repeat bg-center bg-contain float-left mr-2 cursor-pointer"
+          type="radio"
+          name="flexRadioDefault"
+          id="flexRadioOpen"
+          value="Ã…pen"
+          @change="checkRadioButton($event)"
+          checked
+        />
+        <label
+          class="form-check-label inline-block text-gray-800"
+          for="flexRadioOpen"
+          id="radioBoxOpenLabel"
+        >
+          Ã…pen
+        </label>
+      </div>
+      <div class="form-check">
+        <input
+          class="form-check-input appearance-none rounded-full h-4 w-4 border border-gray-300 bg-white checked:bg-blue-600 checked:border-blue-600 focus:outline-none transition duration-200 mt-1 align-top bg-no-repeat bg-center bg-contain float-left mr-2 cursor-pointer"
+          type="radio"
+          name="flexRadioDefault"
+          id="flexRadioPrivate"
+          value="Privat"
+          @change="checkRadioButton($event)"
+        />
+        <label
+          class="form-check-label inline-block text-gray-800"
+          for="flexRadioPrivate"
+          id="radioBoxPrivateLabel"
+        >
+          Privat
+        </label>
+      </div>
+    </div>
+
+    <!-- Title -->
+    <div class="mt-6" :class="{ error: v$.group.name.$errors.length }">
+      <label
+        class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
+        id="titleLabel"
+        >Gruppenavn</label
+      >
+      <input
+        type="text"
+        id="title"
+        class="bg-gray-200 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
+        v-model="v$.group.name.$model"
+        required
+      />
+
+      <!-- error message for title-->
+      <div
+        class="text-red"
+        v-for="(error, index) of v$.group.name.$errors"
+        :key="index"
+      >
+        <div class="text-red-600 text-sm">
+          {{ error.$message }}
+        </div>
+      </div>
+    </div>
+
+    <!-- Select category -->
+    <div class="mt-6">
+      <label
+        class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400"
+        id="selectCategoryLabel"
+        >Kategori</label
+      >
+      <select
+        v-model="v$.group.select.$model"
+        id="categories"
+        class="bg-gray-200 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
+      >
+        <option class="text-gray-400" value="" disabled selected>
+          Select a category
+        </option>
+        <option
+          v-for="category in group.categories"
+          :key="category"
+          class="text-gray-900 text-sm"
+        >
+          {{ category }}
+        </option>
+      </select>
+
+      <!-- error message for select box -->
+      <div
+        class="text-red"
+        v-for="(error, index) of v$.group.select.$errors"
+        :key="index"
+      >
+        <div class="text-red-600 text-sm">
+          {{ error.$message }}
+        </div>
+      </div>
+    </div>
+
+    <!-- Description -->
+    <div class="mt-6" :class="{ error: v$.group.description.$errors.length }">
+      <label
+        class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400"
+        id="descriptionLabel"
+        >Beskrivelse</label
+      >
+      <textarea
+        id="description"
+        rows="4"
+        v-model="v$.group.description.$model"
+        class="block p-2.5 w-full text-sm text-gray-900 bg-gray-200 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
+        required
+      ></textarea>
+
+      <!-- error message for description -->
+      <div
+        class="text-red"
+        v-for="(error, index) of v$.group.description.$errors"
+        :key="index"
+      >
+        <div class="text-red-600 text-sm">
+          {{ error.$message }}
+        </div>
+      </div>
+    </div>
+
+    <!-- Images -->
+    <div class="mt-6">
+      <label
+        class="block mb-2 text-xl font-medium text-gray-900 dark:text-gray-400"
+        id="imageLabel"
+      >
+        Bilde
+      </label>
+
+      <input
+        type="file"
+        ref="file"
+        style="display: none"
+        @change="addImage"
+        multiple
+        accept="image/png, image/jpeg"
+      />
+
+      <!-- Button for adding an image -->
+      <div class="inline-flex rounded-md shadow-sm">
+        <button
+          @click="$refs.file.click()"
+          class="text-black bg-gray-200 hover:bg-grey-800 focus:ring-4 focus:outline-none focus:ring-grey-300 font-medium rounded-lg text-sm sm:w-auto px-5 py-2.5 text-center dark:bg-grey-600 dark:hover:bg-grey-700 dark:focus:ring-grey-800 disabled:opacity-50 cursor-not-allowed"
+          :disabled="imageAdded"
+        >
+          Velg bilde
+        </button>
+
+        <!-- Button for removing an image -->
+        <button
+          class="w-1/12 ml-5 text-white bg-white-500 font-medium rounded-lg text-sm"
+          v-show="imageAdded"
+          @click="removeImage"
+        >
+          <img src="../assets/removeIcon.png" alt="Remove icon image" />
+        </button>
+      </div>
+
+      <!-- Div box for showing all chosen images -->
+      <div v-for="image in group.images" :key="image" class="m-2">
+        <img :src="image" class="w-1/2 inline" alt="Bilde av gjenstanden" />
+      </div>
+    </div>
+
+    <!-- Save item button -->
+    <div class="flex justify-center mt-10">
+      <button
+        @click="saveClicked"
+        class="content-center text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
+        id="saveButton"
+      >
+        Lagre
+      </button>
+    </div>
+  </div>
+</template>
+
+<script>
+import useVuelidate from "@vuelidate/core";
+import { required, helpers, maxLength } from "@vuelidate/validators";
+
+export default {
+  name: "CreateNewGroup.vue",
+
+  setup() {
+    return { v$: useVuelidate() };
+  },
+
+  validations() {
+    return {
+      group: {
+        name: {
+          required: helpers.withMessage(
+            () => "Navnt kan ikke være tom",
+            required
+          ),
+          max: helpers.withMessage(
+            () => `Navnet kan være på max 50 tegn`,
+            maxLength(50)
+          ),
+        },
+        description: {
+          required: helpers.withMessage(
+            () => "Beskrivelsen kan ikke være tom",
+            required
+          ),
+          max: helpers.withMessage(
+            () => `Beskrivelsen kan inneholde max 200 tegn`,
+            maxLength(200)
+          ),
+        },
+        select: {
+          required: helpers.withMessage(() => `Velg en kategori`, required),
+        },
+      },
+    };
+  },
+  data() {
+    return {
+      group: {
+        name: "",
+        select: null,
+        description: "",
+        images: [],
+        categories: ["Borettslag", "Idrettsklubb", "Fritidsklubb"],
+        radio: null,
+      },
+      imageThere: false,
+    };
+  },
+  computed: {
+    imageAdded: function () {
+      if (this.imageThere) {
+        return true;
+      } else {
+        return false;
+      }
+    },
+  },
+  methods: {
+    removeImage: function () {
+      this.group.images.pop();
+      this.imageThere = false;
+      console.log("Bilder nå: " + this.group.images.length);
+    },
+    checkRadioButton: function (event) {
+      this.group.radio = event.target.value;
+      console.log(this.group.radio);
+    },
+    checkValidation: function () {
+      console.log("sjekker validering");
+
+      this.v$.group.$touch();
+      if (this.v$.group.$invalid) {
+        console.log("Invalid, avslutter...");
+        return false;
+      }
+
+      console.log("validert!");
+      return true;
+    },
+
+    async saveClicked() {
+      console.log("Attempting to save item");
+
+      if (this.checkValidation()) {
+        console.log("validert, videre...");
+        console.log("Navn: " + this.group.name);
+        console.log("Synlighet: " + this.group.radio);
+        console.log("Kategori: " + this.group.select);
+        console.log("Beskrivelse: " + this.group.description);
+        console.log("bilder: " + this.group.images);
+      }
+    },
+
+    addImage: function (event) {
+      console.log(event.target.files);
+      this.group.images.push(URL.createObjectURL(event.target.files[0]));
+      console.log("antall bilder: " + this.group.images.length);
+      this.imageThere = true;
+      console.log("image: " + this.imageThere);
+    },
+  },
+};
+</script>
diff --git a/src/components/HelloWorld.vue b/src/components/HelloWorld.vue
index 84bd14e103584c8f13019ee33fe36e9a3f1e3ba3..ecc5bf651ccbb96fd5cc76ffaa9a204ea7d99310 100644
--- a/src/components/HelloWorld.vue
+++ b/src/components/HelloWorld.vue
@@ -1,78 +1,11 @@
 <template>
-  <v-container>
-    <v-row class="text-center">
-      <v-col cols="12">
-        <v-img
-          :src="require('../assets/logo.svg')"
-          class="my-3"
-          contain
-          height="200"
-        />
-      </v-col>
+  <div class="flex justify-center">
+    <router-link to="/" class="m-6">Logg inn</router-link>
 
-      <v-col class="mb-4">
-        <h1 class="display-2 font-weight-bold mb-3">
-          Welcome to the Vuetify 3 Beta
-        </h1>
+    <router-link to="/register" class="m-6">Registrer deg</router-link>
 
-        <p class="subheading font-weight-regular">
-          For help and collaboration with other Vuetify developers,
-          <br />please join our online
-          <a href="https://community.vuetifyjs.com" target="_blank"
-            >Discord Community</a
-          >
-        </p>
-      </v-col>
-
-      <v-col class="mb-5" cols="12">
-        <h2 class="headline font-weight-bold mb-5">What's next?</h2>
-
-        <v-row justify="center">
-          <a
-            v-for="(next, i) in whatsNext"
-            :key="i"
-            :href="next.href"
-            class="subheading mx-3"
-            target="_blank"
-          >
-            {{ next.text }}
-          </a>
-        </v-row>
-      </v-col>
-
-      <v-col class="mb-5" cols="12">
-        <h2 class="headline font-weight-bold mb-5">Important Links</h2>
-
-        <v-row justify="center">
-          <a
-            v-for="(link, i) in importantLinks"
-            :key="i"
-            :href="link.href"
-            class="subheading mx-3"
-            target="_blank"
-          >
-            {{ link.text }}
-          </a>
-        </v-row>
-      </v-col>
-
-      <v-col class="mb-5" cols="12">
-        <h2 class="headline font-weight-bold mb-5">Ecosystem</h2>
-
-        <v-row justify="center">
-          <a
-            v-for="(eco, i) in ecosystem"
-            :key="i"
-            :href="eco.href"
-            class="subheading mx-3"
-            target="_blank"
-          >
-            {{ eco.text }}
-          </a>
-        </v-row>
-      </v-col>
-    </v-row>
-  </v-container>
+    <router-link to="/about" class="m-6">Om BoCo</router-link>
+  </div>
 </template>
 
 <script>
@@ -80,52 +13,7 @@ export default {
   name: "HelloWorld",
 
   data: () => ({
-    ecosystem: [
-      {
-        text: "vuetify-loader",
-        href: "https://github.com/vuetifyjs/vuetify-loader",
-      },
-      {
-        text: "github",
-        href: "https://github.com/vuetifyjs/vuetify",
-      },
-      {
-        text: "awesome-vuetify",
-        href: "https://github.com/vuetifyjs/awesome-vuetify",
-      },
-    ],
-    importantLinks: [
-      {
-        text: "Chat",
-        href: "https://community.vuetifyjs.com",
-      },
-      {
-        text: "Made with Vuetify",
-        href: "https://madewithvuejs.com/vuetify",
-      },
-      {
-        text: "Twitter",
-        href: "https://twitter.com/vuetifyjs",
-      },
-      {
-        text: "Articles",
-        href: "https://medium.com/vuetify",
-      },
-    ],
-    whatsNext: [
-      {
-        text: "Explore components",
-        href: "https://vuetifyjs.com",
-      },
-      {
-        text: "Roadmap",
-        href: "https://vuetifyjs.com/introduction/roadmap/",
-      },
-      {
-        text: "Frequently Asked Questions",
-        href: "https://vuetifyjs.com/getting-started/frequently-asked-questions",
-      },
-    ],
-  }),
-};
+
+}),
+}
 </script>
diff --git a/src/components/ItemCard.vue b/src/components/ItemCard.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c7b866eefac807e242c8108a5b9323eb7159040d
--- /dev/null
+++ b/src/components/ItemCard.vue
@@ -0,0 +1,31 @@
+<template>
+  <div class="mt-5">
+    <div class="w-4/5 rounded bg-gray-200">
+      <img
+        class="w-full"
+        :src="item.img || require('../assets/default-product.png')"
+        alt="Item image"
+      />
+      <div class="p-1 m-1">
+        <p class="text-gray-700 text-xs font-bold" id="adress">
+          {{ item.adresse }}
+        </p>
+        <p class="font-bold text-sm" id="title">{{ item.title }}</p>
+        <p class="text-gray-700 text-xs" id="price">{{ item.price }} kr</p>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    item: {
+      img: String,
+      adresse: String,
+      title: String,
+      price: Number,
+    },
+  },
+};
+</script>
diff --git a/src/components/NewPasswordForm.vue b/src/components/NewPasswordForm.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c86145ce10db183a6c8781b18c95c99c0e7c53b0
--- /dev/null
+++ b/src/components/NewPasswordForm.vue
@@ -0,0 +1,74 @@
+<template>
+  <div>
+    <v-col align="center" justify="space-around" class="mt-16">
+      <v-img
+        max-width="45%"
+        :src="require('../assets/logo3.svg')"
+        align="center"
+      />
+    </v-col>
+
+    <v-form ref="form" v-model="valid" lazy-validation class="mt-8">
+      <v-text-field
+        v-model="user.password"
+        :rules="[rules.required, rules.min]"
+        :type="'password'"
+        name="input-10-1"
+        label="Passord"
+        counter
+      ></v-text-field>
+
+      <v-text-field
+        v-model="user.rePassword"
+        :rules="[rules.required, rules.min, rules.passwordConfirmation]"
+        :type="'password'"
+        name="input-10-1"
+        label="Confirm Password"
+        counter
+      ></v-text-field>
+
+      <v-col justify="space-around" align="center">
+        <v-btn
+          :disabled="!valid"
+          color="success"
+          class="mb-4 mt-4"
+          width="50%"
+          height="40px"
+          @click="setNewPassword"
+        >
+          Endre passord
+        </v-btn>
+      </v-col>
+    </v-form>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "NewPasswordForm.vue",
+
+  data() {
+    return {
+      user: {
+        password: "",
+        rePassword: "",
+      },
+
+      valid: true,
+      rules: {
+        required: (value) => !!value || "Feltet er påkrevd",
+        min: (v) => v.length >= 8 || "Minimum 8 tegn",
+        passwordConfirmation: (v) =>
+          v === this.user.password || "Passordene må være like",
+      },
+    };
+  },
+
+  methods: {
+    async setNewPassword() {},
+    validate() {
+      this.$refs.form.validate();
+    },
+  },
+};
+</script>
diff --git a/src/components/RegisterFormComponent.vue b/src/components/RegisterFormComponent.vue
index b69d38827a90245b00a8c961b4ef816511074bd6..240895bffbe2fe98be228f19e2d7549f3bc24227 100644
--- a/src/components/RegisterFormComponent.vue
+++ b/src/components/RegisterFormComponent.vue
@@ -1,155 +1,250 @@
 <template>
-  <v-form ref="form" v-model="valid" lazy-validation>
-    <v-text-field
-      v-model="email"
-      :rules="emailRules"
-      label="E-mail"
-      required
-    ></v-text-field>
-
-    <v-text-field
-      v-model="password"
-      :counter="32"
-      :rules="passwordRules"
-      label="Passord"
-      :append-icon="passwordHidden ? 'mdi-eye' : 'mdi-eye-off'"
-      :type="passwordHidden ? 'text' : 'password'"
-      @click:append="passwordHidden = !passwordHidden"
-      required
-    ></v-text-field>
-
-    <v-container class="grey lighten-5">
-      <v-row>
-        <v-text-field
-          class="pr-2"
-          v-model="firstName"
-          :counter="32"
-          :rules="firstNameRules"
-          label="Fornavn"
-          required
-        ></v-text-field>
-
-        <v-text-field
-          class="pl-2"
-          v-model="lastName"
-          :counter="32"
-          :rules="lastNameRules"
-          label="Etternavn"
-          required
-        ></v-text-field>
-      </v-row>
-    </v-container>
-
-    <v-text-field
-      v-model="address"
-      :counter="32"
-      :rules="addressRules"
-      label="Addresse"
-      required
-    ></v-text-field>
-
-    <!-- <v-text-field
-      v-model="confirmPassword"
-      :rules="confirmPasswordRules"
-      label="Bekreft passord"
-      :append-icon="confirmPasswordHidden ? 'mdi-eye' : 'mdi-eye-off'"
-      :type="confirmPasswordHidden ? 'text' : 'password'"
-      @click:append="confirmPasswordHidden = !confirmPasswordHidden"
-      required
-    ></v-text-field> -->
-
-    <!-- <v-select
-      v-model="select"
-      :items="items"
-      :rules="[(v) => !!v || 'Item is required']"
-      label="Item"
-      required
-    ></v-select> -->
-
-    <!-- <v-checkbox
-      v-model="checkbox"
-      :rules="[(v) => !!v || 'You must agree to continue!']"
-      label="Do you agree?"
-      required
-    ></v-checkbox> -->
-
-    <v-btn :disabled="!valid" color="success" class="mr-4" @click="submit()"
-      >Registrer</v-btn
-    >
-
-    <v-btn color="error" class="mr-4" @click="reset()">Tøm felter</v-btn>
-  </v-form>
+  <section
+    class="max-w-4xl p-6 mx-auto bg-white rounded-md shadow-md dark:bg-gray-800"
+  >
+    <h2 class="text-lg font-semibold text-gray-700 capitalize dark:text-white">
+      Opprett ny bruker
+    </h2>
+
+    <form @submit.prevent>
+      <div class="grid grid-cols-1 gap-6 mt-4 sm:grid-cols-2">
+        <div>
+          <label class="text-gray-700 dark:text-gray-200" for="email"
+            >E-mail</label
+          >
+          <input
+            v-model="email"
+            id="email"
+            type="email"
+            class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-200 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
+          />
+        </div>
+
+        <div>
+          <label class="text-gray-700 dark:text-gray-200" for="password"
+            >Passord</label
+          >
+          <input
+            v-model="password"
+            id="password"
+            type="password"
+            class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-200 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
+          />
+        </div>
+
+        <div>
+          <label class="text-gray-700 dark:text-gray-200" for="confirmPassword"
+            >Bekreft Passord</label
+          >
+          <input
+            v-model="confirmPassword"
+            id="confirmPassword"
+            type="password"
+            class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-200 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
+          />
+        </div>
+
+        <div>
+          <label class="text-gray-700 dark:text-gray-200" for="firstName"
+            >Fornavn</label
+          >
+          <input
+            data-test="firstNameTest"
+            v-model="firstName"
+            id="firstName"
+            type="text"
+            class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-200 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
+          />
+        </div>
+
+        <div>
+          <label class="text-gray-700 dark:text-gray-200" for="lastName"
+            >Etternavn</label
+          >
+          <input
+            v-model="lastName"
+            id="lastName"
+            type="text"
+            class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-200 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
+          />
+        </div>
+
+        <div>
+          <label class="text-gray-700 dark:text-gray-200" for="address"
+            >Addresse</label
+          >
+          <input
+            v-model="address"
+            id="address"
+            type="text"
+            class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-200 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
+          />
+        </div>
+      </div>
+
+      <div class="flex justify-end mt-6">
+        <button
+          class="px-6 py-2 leading-5 text-white transition-colors duration-200 transform bg-gray-700 rounded-md hover:bg-gray-600 focus:outline-none focus:bg-gray-600"
+          @click="submit()"
+          type="submit"
+          :disabled="loading"
+        >
+          <div v-if="loading">
+            <div v-if="loading" class="lds-ring">
+              <div></div>
+              <div></div>
+              <div></div>
+              <div></div>
+            </div>
+          </div>
+          <div v-else>Lagre</div>
+        </button>
+      </div>
+    </form>
+  </section>
+  <ul data-test="errorMessageList">
+    <li v-if="errorMessage" data-test="customErrorMsg">{{ errorMessage }}</li>
+    <li v-for="error of v$.$errors" :key="error.$uid">
+      <!-- {{ error.$validator }} -->
+      Field
+      {{ error.$property }}
+      has error:
+      {{ error.$message }}
+    </li>
+  </ul>
 </template>
+
 <script>
-import axios from "axios";
+import useVuelidate from "@vuelidate/core";
+import { doLogin, registerUser } from "@/utils/apiutil";
+import { required, email, minLength, sameAs } from "@vuelidate/validators";
 
-export default {
-  data: () => ({
-    passwordHidden: false,
-    // confirmPasswordHidden: false,
-    valid: true,
-    firstName: "",
-    firstNameRules: [
-      (v) => !!v || "Fornavn er påkrevd",
-      (v) => (v && v.length <= 32) || "Fornavn må være mindre enn 32 bokstaver",
-    ],
-    lastName: "",
-    lastNameRules: [
-      (v) => !!v || "Etternavn er påkrevd",
-      (v) =>
-        (v && v.length <= 32) || "Etternavn må være mindre enn 32 bokstaver",
-    ],
-    address: "",
-    addressRules: [
-      (v) => !!v || "Addresse er påkrevd",
-      (v) =>
-        (v && v.length <= 32) || "Addresse må være mindre enn 32 bokstaver",
-    ],
-    password: "",
-    passwordRules: [
-      (v) => !!v || "Passord er påkrevd",
-      (v) => (v && v.length <= 32) || "Passord må være mindre enn 32 tegn",
-      (v) => (v && v.length >= 8) || "Passord må være større enn 8 tegn",
-    ],
-    // confirmPassword: "",
-    // confirmPasswordRules: [
-    //   (v) => !!v || "Passord er påkrevd",
-    //   (v) => (v && v.length <= 32) || "Passord må være mindre enn 32 bokstaver",
-    //   // (v) => v === this.password || "Passordene må være like",
-    // ],
-    email: "",
-    emailRules: [
-      (v) => !!v || "E-mail is required",
-      (v) => /.+@.+\..+/.test(v) || "E-mail must be valid",
-    ],
-    // select: null,
-    // items: ["Item 1", "Item 2", "Item 3", "Item 4"],
-    // checkbox: false,
-  }),
+// const isEmailTaken = (value) =>
+// fetch(`/api/unique/${value}`).then((r) => r.json()); // check the email in the server
 
+export default {
+  setup: () => ({ v$: useVuelidate() }),
+  data() {
+    return {
+      errorMessage: "",
+      loading: false,
+      email: "",
+      password: "",
+      confirmPassword: "",
+      firstName: "",
+      lastName: "",
+      address: "",
+    };
+  },
+  validations() {
+    return {
+      email: {
+        required,
+        email,
+        // isUnique: helpers.withAsync(isEmailTaken),
+      },
+      password: {
+        required,
+        minLength: minLength(8),
+      },
+      confirmPassword: { sameAs: sameAs(this.password) },
+      firstName: { required },
+      lastName: { required },
+      address: { required },
+    };
+  },
   methods: {
-    submit() {
-      console.log("Attempting to register user");
-      this.valid = this.$refs.form.validate();
-      if (!this.valid) return;
-      this.valid = false;
-      console.log("User is validated");
-      axios
-        .post("http://localhost:3000/api/register", {
-          email: this.email,
-          firstName: this.firstName,
-          lastname: this.lastName,
-          password: this.password,
-          address: this.address,
-        })
-        .then(console.log("Sent"))
-        .catch((e) => console.log(e));
+    async submit() {
+      //Display loading symbol
+      this.loading = true;
+
+      //Validate form
+      const result = await this.v$.$validate();
+      if (!result) {
+        this.loading = false;
+        return;
+      }
+
+      //Send a request to create a user and save success as a bool
+      const userCreated = await this.sendRegisterRequest();
+
+      //If a user is created succsessfully, try to login
+      //If we get this far, we will be pushed anyway so there is no point updating "loading"
+      if (!userCreated) {
+        this.errorMessage = "Could not create user.";
+        return;
+      }
+
+      const loginRequest = {
+        email: this.email,
+        password: this.password,
+      };
+
+      const loginResponse = await doLogin(loginRequest);
+
+      if (loginResponse === "Failed login") {
+        this.errorMessage = "Failed to log in with new user";
+        this.$store.commit("logout");
+        this.$router.push("/login");
+        return;
+      }
+
+      this.$store.commit("saveToken", loginResponse);
+      this.$router.push("/");
     },
-    reset() {
-      this.$refs.form.reset();
-      this.$refs.form.resetValidation();
-      this.valid = true;
+    async sendRegisterRequest() {
+      const registerInfo = {
+        email: this.email,
+        firstName: this.firstName,
+        lastname: this.lastName,
+        password: this.password,
+        address: this.address,
+      };
+
+      const response = await registerUser(registerInfo);
+
+      if (response.status === 200) return true;
+      return false;
     },
   },
 };
 </script>
+
+<style scoped>
+/* https://loading.io/css/ */
+.lds-ring {
+  display: inline-block;
+  position: relative;
+  width: 20px;
+  height: 20px;
+}
+.lds-ring div {
+  box-sizing: border-box;
+  display: block;
+  position: absolute;
+  width: 16px;
+  height: 16px;
+  margin: 2px;
+  border: 2px solid #fff;
+  border-radius: 50%;
+  animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
+  border-color: #fff transparent transparent transparent;
+}
+.lds-ring div:nth-child(1) {
+  animation-delay: -0.45s;
+}
+.lds-ring div:nth-child(2) {
+  animation-delay: -0.3s;
+}
+.lds-ring div:nth-child(3) {
+  animation-delay: -0.15s;
+}
+@keyframes lds-ring {
+  0% {
+    transform: rotate(0deg);
+  }
+  100% {
+    transform: rotate(360deg);
+  }
+}
+</style>
diff --git a/src/components/SearchItemListComponent.vue b/src/components/SearchItemListComponent.vue
new file mode 100644
index 0000000000000000000000000000000000000000..69950032651b044300e126f2c828d41ae5d950d1
--- /dev/null
+++ b/src/components/SearchItemListComponent.vue
@@ -0,0 +1,82 @@
+<template>
+  <section class="relative w-full max-w-md px-5 py-4 mx-auto rounded-md">
+    <div class="relative" id="searchComponent">
+      <span class="absolute inset-y-0 left-0 flex items-center pl-3">
+        <svg class="w-5 h-5 text-gray-400" viewBox="0 0 24 24" fill="none">
+          <path
+            d="M21 21L15 15M17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10Z"
+            stroke="currentColor"
+            stroke-width="2"
+            stroke-linecap="round"
+            stroke-linejoin="round"
+          ></path>
+        </svg>
+      </span>
+
+      <input
+        type="text"
+        id="searchInput"
+        class="w-full py-3 pl-10 pr-4 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
+        placeholder="Search"
+        v-model="search"
+      />
+    </div>
+
+    <div class="absolute inset-x-0 px-6 py-3 mt-4 border-2 border-slate-500">
+      <div class="grid grid-cols-2">
+        <ItemCard v-for="item in searchedItems" :key="item" :item="item" />
+      </div>
+    </div>
+  </section>
+</template>
+
+<script>
+import ItemCard from "@/components/ItemCard";
+export default {
+  name: "SearchItemListComponent",
+
+  components: {
+    ItemCard,
+  },
+
+  computed: {
+    searchedItems() {
+      let filteredItems = [];
+
+      filteredItems = this.items.filter(
+        (p) =>
+          p.title.toLowerCase().includes(this.search.toLowerCase()) ||
+          p.adresse.toLowerCase().includes(this.search.toLowerCase()) ||
+          p.price === Number(this.search)
+      );
+
+      return filteredItems;
+    },
+  },
+
+  /**
+   * Her må det lages en metode som henter alle items (i en gruppe) fra databasen.
+   * De kan deretter bli pusha inn i items array, og da burde de bli displayet i lista.
+   * Når denne metoden er på plass kan items[] i data tømmes. Da vil alt dataen komme fra db.
+   */
+
+  data() {
+    return {
+      items: [
+        { img: "", adresse: "Oslo", title: "Dyson", price: 1000 },
+
+        { img: "", adresse: "Trondheim", title: "Gressklipper", price: 500 },
+
+        { img: "", adresse: "Bergen", title: "Bil", price: 500 },
+      ],
+      item: {
+        img: "",
+        adresse: "",
+        title: "",
+        price: 0,
+      },
+      search: "",
+    };
+  },
+};
+</script>
diff --git a/src/components/UserProfileComponents/LargeProfileCard.vue b/src/components/UserProfileComponents/LargeProfileCard.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7c5c036f8103be9c42b62d0c818dfa229af2f8cd
--- /dev/null
+++ b/src/components/UserProfileComponents/LargeProfileCard.vue
@@ -0,0 +1,141 @@
+<template>
+  <div
+    class="max-w-sm bg-white rounded-lg border border-gray-200 shadow-md dark:bg-gray-800 dark:border-gray-700"
+  >
+    <div v-show="isCurrentUser" class="flex justify-end px-4 pt-4">
+      <button
+        id="dropdownDefault"
+        data-dropdown-toggle="dropdown"
+        @click="dropdown = !dropdown"
+        class="hidden sm:inline-block text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-1.5"
+        type="button"
+      >
+        <svg
+          class="w-6 h-6"
+          fill="currentColor"
+          viewBox="0 0 20 20"
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <path
+            d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z"
+          ></path>
+        </svg>
+      </button>
+
+      <div
+        id="dropdown"
+        v-show="dropdown"
+        zindex="2"
+        class="z-10 w-44 text-base list-none bg-white rounded divide-y divide-gray-100 shadow dark:bg-gray-700"
+      >
+        <ul class="py-1" aria-labelledby="dropdownDefault">
+          <li>
+            <router-link
+              to=""
+              class="block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
+              >Mine gjenstander</router-link
+            >
+          </li>
+          <li>
+            <router-link
+              to=""
+              class="block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
+              >Mine grupper
+            </router-link>
+          </li>
+          <li>
+            <router-link
+              to=""
+              class="block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
+              >Leiehistorikk</router-link
+            >
+          </li>
+          <li>
+            <router-link
+              to="/newPassword"
+              class="block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
+              >Endre passord</router-link
+            >
+          </li>
+          <li>
+            <router-link
+              to=""
+              class="block py-2 px-4 text-sm text-red-600 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
+              >Slett bruker</router-link
+            >
+          </li>
+        </ul>
+      </div>
+    </div>
+    <div class="flex flex-col items-center pb-10">
+      <img
+        class="mb-3 w-24 h-24 rounded-full shadow-lg"
+        src="../../assets/defaultUserProfileImage.jpg"
+        alt="Profile picture"
+      />
+      <h5 class="mb-1 text-xl font-medium text-gray-900 dark:text-white">
+        {{ user.firstName }} {{ user.lastName }}
+      </h5>
+      <div>
+        <rating-component :rating="renterRating" :ratingType="'Leietaker'" />
+        <rating-component :rating="ownerRating" :ratingType="'Utleier'" />
+      </div>
+
+      <div v-show="!isCurrentUser" class="flex mt-4 space-x-3 lg:mt-6">
+        <a
+          href="#"
+          class="inline-flex items-center py-2 px-4 text-sm font-medium text-center text-gray-900 bg-white rounded-lg border border-gray-300 hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-gray-200 dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-700 dark:focus:ring-gray-700"
+          >Ã…pne chat</a
+        >
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import RatingComponent from "@/components/UserProfileComponents/RatingComponent.vue";
+import { parseCurrentUser } from "@/utils/token-utils";
+import { getUser, getRenterRating, getOwnerRating } from "@/utils/apiutil";
+import router from "@/router";
+
+export default {
+  name: "LargeProfileCard",
+  data() {
+    return {
+      user: {},
+      currentUser: {},
+      id: -1,
+      isCurrentUser: false,
+      renterRating: -1, //getRenterRating(this.userID),
+      ownerRating: -1, //getOwnerRating(this.userID),
+      dropdown: false,
+    };
+  },
+  components: {
+    RatingComponent,
+  },
+  methods: {
+    async getUser() {
+      this.currentUser = parseCurrentUser();
+      this.id = router.currentRoute.value.params.id;
+      if (this.id == this.currentUser.account_id) {
+        this.isCurrentUser = true;
+        this.user = this.currentUser;
+        return;
+      }
+      this.user = await getUser(this.id);
+      this.renterRating = getRenterRating(this.id);
+      this.ownerRating = getOwnerRating(this.id);
+    },
+    getProfilePicture() {
+      /* if (this.user.picture != "") {
+        return this.user.picture;
+      } */
+      return "../assets/defaultUserProfileImage.jpg";
+    },
+  },
+  beforeMount() {
+    this.getUser();
+  },
+};
+</script>
diff --git a/src/components/UserProfileComponents/RatingComponent.vue b/src/components/UserProfileComponents/RatingComponent.vue
new file mode 100644
index 0000000000000000000000000000000000000000..662b9607911697c89421e7c4727b44caa93dfe4c
--- /dev/null
+++ b/src/components/UserProfileComponents/RatingComponent.vue
@@ -0,0 +1,61 @@
+<template>
+  <ul v-if="compRating != -1" class="flex justify-center">
+    <li>
+      <p class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">
+        {{ ratingType }}:&nbsp;
+      </p>
+    </li>
+    <li v-for="i in 5" :key="i">
+      <svg
+        :class="getFill(i)"
+        fill="currentColor"
+        viewBox="0 0 20 20"
+        xmlns="http://www.w3.org/2000/svg"
+      >
+        <path
+          d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"
+        ></path>
+      </svg>
+    </li>
+    <li>
+      <p class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">
+        {{ compRating }} out of 5
+      </p>
+    </li>
+  </ul>
+  <ul v-else class="flex justify-center">
+    <li>
+      <p class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">
+        {{ ratingType }}:&nbsp;
+      </p>
+    </li>
+    <li>
+      <p class="ml-2 text-sm font-medium text-gray-500 dark:text-gray-400">
+        Rating ikke tilgjengelig
+      </p>
+    </li>
+  </ul>
+</template>
+
+<script>
+export default {
+  name: "RatingComponent",
+  data() {
+    return {
+      compRating: this.rating + 0,
+    };
+  },
+  props: {
+    rating: Number,
+    ratingType: String,
+  },
+  methods: {
+    getFill(i) {
+      if (i <= this.rating) {
+        return "w-5 h-5 text-yellow-400";
+      }
+      return "w-5 h-5 text-gray-300 dark:text-gray-500";
+    },
+  },
+};
+</script>
diff --git a/src/components/UserProfileComponents/UserListItemCard.vue b/src/components/UserProfileComponents/UserListItemCard.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4da140e21610587c8e88953ed9b17572c9bef98a
--- /dev/null
+++ b/src/components/UserProfileComponents/UserListItemCard.vue
@@ -0,0 +1,40 @@
+<template>
+  <div
+    class="select-none cursor-pointer hover:bg-gray-50 flex flex-1 items-center p-4"
+  >
+    <div class="flex flex-col w-10 h-10 justify-center items-center mr-4">
+      <router-link to="">
+        <img alt="profil" :src="getProfilePicture" />
+      </router-link>
+    </div>
+    <div class="flex-1 pl-1">
+      <div class="font-medium dark:text-white">
+        {{ user.first_name }} {{ user.last_name }}
+      </div>
+    </div>
+    <div class="flex flex-row justify-center">
+      <button class="w-10 text-right flex justify-end">Ã…pne chat</button>
+      <button v-if="admin" class="w-10 text-right flex justify-end">
+        Fjern bruker
+      </button>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "UserListItem",
+  props: {
+    user: Object,
+    admin: Boolean,
+  },
+  methods: {
+    getProfilePicture() {
+      if (this.user.picture != "") {
+        return this.user.picture;
+      }
+      return "../assets/defaultUserProfileImage.jpg";
+    },
+  },
+};
+</script>
diff --git a/src/main.js b/src/main.js
index 34900f2ef3e7361998cbdee5516fd55fcd5c3ff7..32472cfc34b97f2df35e1d89704bc9d91e39c6d1 100644
--- a/src/main.js
+++ b/src/main.js
@@ -2,9 +2,6 @@ import { createApp } from "vue";
 import App from "./App.vue";
 import router from "./router";
 import store from "./store";
-import { loadFonts } from "./plugins/webfontloader";
 import "./index.css";
 
-loadFonts();
-
 createApp(App).use(router).use(store).mount("#app");
diff --git a/src/plugins/vuetify.js b/src/plugins/vuetify.js
deleted file mode 100644
index 8968900a4937011a5bcf7423449220a683056722..0000000000000000000000000000000000000000
--- a/src/plugins/vuetify.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Styles
-import "@mdi/font/css/materialdesignicons.css";
-import "vuetify/styles";
-
-// Vuetify
-import { createVuetify } from "vuetify";
-
-export default createVuetify();
-// https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides
diff --git a/src/plugins/webfontloader.js b/src/plugins/webfontloader.js
deleted file mode 100644
index e86aa7db6b15c1b2bd2e3a40c7df2f2c7fa663bb..0000000000000000000000000000000000000000
--- a/src/plugins/webfontloader.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * plugins/webfontloader.js
- *
- * webfontloader documentation: https://github.com/typekit/webfontloader
- */
-
-export async function loadFonts() {
-  const webFontLoader = await import(
-    /* webpackChunkName: "webfontloader" */ "webfontloader"
-  );
-
-  webFontLoader.load({
-    google: {
-      families: ["Roboto:100,300,400,500,700,900&display=swap"],
-    },
-  });
-}
diff --git a/src/utils/token-utils.js b/src/utils/token-utils.js
new file mode 100644
index 0000000000000000000000000000000000000000..ba37787fbb3f43cfdce7ba11aba70d2d3c8b5bff
--- /dev/null
+++ b/src/utils/token-utils.js
@@ -0,0 +1,16 @@
+import jwt_decode from "jwt-decode";
+import store from "@/store";
+
+export function tokenHeader() {
+  let token = store.state.user.token;
+  return { Authorization: token };
+}
+
+export function parseCurrentUser() {
+  let token = store.state.user.token;
+  return jwt_decode(token);
+}
+
+export function parseUserFromToken(token) {
+  return jwt_decode(token);
+}
diff --git a/src/views/CreateNewGroupView.vue b/src/views/CreateNewGroupView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d3b69d68220d7cd3a1cc3cd4fa4e3398feafe696
--- /dev/null
+++ b/src/views/CreateNewGroupView.vue
@@ -0,0 +1,15 @@
+<template>
+  <CreateNewGroup></CreateNewGroup>
+</template>
+
+<script>
+import CreateNewGroup from "@/components/CreateNewGroup";
+export default {
+  name: "CreateNewGroupView.vue",
+  components: {
+    CreateNewGroup,
+  },
+};
+</script>
+
+<style scoped></style>
diff --git a/src/views/NewPasswordView.vue b/src/views/NewPasswordView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..bcccd80e96de1cf888b6cc0adb82baa0e48fc8fd
--- /dev/null
+++ b/src/views/NewPasswordView.vue
@@ -0,0 +1,23 @@
+<template>
+  <div class="newPasswordPage">
+    <NewPasswordForm></NewPasswordForm>
+  </div>
+</template>
+
+<script>
+import NewPasswordForm from "@/components/NewPasswordForm";
+export default {
+  name: "NewPasswordView.vue",
+  components: {
+    NewPasswordForm,
+  },
+};
+</script>
+
+<style scoped>
+.newPasswordPage {
+  background-color: white;
+  height: 100%;
+  overflow: auto;
+}
+</style>
diff --git a/src/views/ProfileView.vue b/src/views/ProfileView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..cfd2cefd902017ad7b867b7cfe447cce5648cf07
--- /dev/null
+++ b/src/views/ProfileView.vue
@@ -0,0 +1,14 @@
+<!-- View for looking at different profile display methods -->
+<template>
+  <large-profile-card :isCurrentUser="true" />
+</template>
+
+<script>
+import LargeProfileCard from "@/components/UserProfileComponents/LargeProfileCard.vue";
+
+export default {
+  components: {
+    LargeProfileCard,
+  },
+};
+</script>
diff --git a/src/views/RegisterView.vue b/src/views/RegisterView.vue
index 9d2ee691f97a923ea3fde5a7d1881792a252b801..c1478be27a6919308ca75adad5a1df3aca8303a3 100644
--- a/src/views/RegisterView.vue
+++ b/src/views/RegisterView.vue
@@ -1,5 +1,7 @@
 <template>
-  <register-form-component id="form" class="pa-8" />
+  <div class="h-screen bg-gray-200 content-center grid place-items-center">
+    <RegisterFormComponent />
+  </div>
 </template>
 
 <script>
@@ -11,10 +13,3 @@ export default {
   },
 };
 </script>
-
-<style scoped>
-#form {
-  max-width: 600px;
-  margin: auto;
-}
-</style>
diff --git a/src/views/SearchItemListView.vue b/src/views/SearchItemListView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..288fa367f2da5f0df7f164f4538a35ecfca62db1
--- /dev/null
+++ b/src/views/SearchItemListView.vue
@@ -0,0 +1,15 @@
+<template>
+  <SearchItemListComponent></SearchItemListComponent>
+</template>
+
+<script>
+import SearchItemListComponent from "@/components/SearchItemListComponent";
+export default {
+  name: "SearchItemListView",
+  components: {
+    SearchItemListComponent,
+  },
+};
+</script>
+
+<style scoped></style>
diff --git a/tailwind.config.js b/tailwind.config.js
index f521631db48dc78b5a6597a6552d9d95ecaee4a5..7cd4f37efd95627b8f362e1b210fd12b384925d9 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,4 +1,5 @@
 module.exports = {
+  darkMode: "class",
   content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
   theme: {
     extend: {},
diff --git a/tests/unit/RegisterUserComponent.spec.js b/tests/unit/RegisterUserComponent.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..a13d18e437230618a1d38e19b9c7bb00d27c1d7f
--- /dev/null
+++ b/tests/unit/RegisterUserComponent.spec.js
@@ -0,0 +1,50 @@
+import { mount } from "@vue/test-utils";
+import RegisterFormComponent from "@/components/RegisterFormComponent";
+
+describe("RegisterFormComponent", () => {
+  let wrapper;
+
+  beforeEach(() => {
+    wrapper = mount(RegisterFormComponent);
+  });
+
+  it("renders correctly", () => {
+    expect(wrapper.element).toMatchSnapshot();
+  });
+
+  it("is instantiated", () => {
+    expect(wrapper.exists()).toBeTruthy();
+  });
+
+  it("renders error message to user", async () => {
+    await wrapper.setData({ errorMessage: "test message" });
+    expect(wrapper.find('li[data-test="customErrorMsg"]').text()).toBe(
+      "test message"
+    );
+  });
+
+  it("renders the h2 text correctly", () => {
+    expect(wrapper.find("h2").text()).toBe("Opprett ny bruker");
+  });
+
+  it("has a button", () => {
+    expect(wrapper.exists("button")).toBe(true);
+  });
+
+  it("updates data when field is updated", async () => {
+    await wrapper.find('input[data-test="firstNameTest"]').setValue("Gunnar");
+    expect(wrapper.vm.firstName).toBe("Gunnar");
+  });
+
+  it("displays 5 error messages when submit is clicked with no data", async () => {
+    await wrapper.find("button").trigger("click");
+    expect(wrapper.findAll("li").length).toBe(5);
+  });
+
+  /*   it("button click with correct sum", () => {
+    wrapper.setData({ guess: "15" });
+    const button = wrapper.find("button");
+    button.trigger("click");
+    expect(wrapper.vm.message).toBe("SUCCESS!");
+  }); */
+});
diff --git a/tests/unit/__snapshots__/RegisterUserComponent.spec.js.snap b/tests/unit/__snapshots__/RegisterUserComponent.spec.js.snap
new file mode 100644
index 0000000000000000000000000000000000000000..f1a63d05fc1ff431b8677b83e799442934955b68
--- /dev/null
+++ b/tests/unit/__snapshots__/RegisterUserComponent.spec.js.snap
@@ -0,0 +1,123 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`RegisterFormComponent renders correctly 1`] = `
+<div
+  data-v-app=""
+>
+  
+  <section
+    class="max-w-4xl p-6 mx-auto bg-white rounded-md shadow-md dark:bg-gray-800"
+  >
+    <h2
+      class="text-lg font-semibold text-gray-700 capitalize dark:text-white"
+    >
+       Opprett ny bruker 
+    </h2>
+    <form>
+      <div
+        class="grid grid-cols-1 gap-6 mt-4 sm:grid-cols-2"
+      >
+        <div>
+          <label
+            class="text-gray-700 dark:text-gray-200"
+            for="email"
+          >
+            E-mail
+          </label>
+          <input
+            class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-200 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
+            id="email"
+            type="email"
+          />
+        </div>
+        <div>
+          <label
+            class="text-gray-700 dark:text-gray-200"
+            for="password"
+          >
+            Passord
+          </label>
+          <input
+            class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-200 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
+            id="password"
+            type="password"
+          />
+        </div>
+        <div>
+          <label
+            class="text-gray-700 dark:text-gray-200"
+            for="confirmPassword"
+          >
+            Bekreft Passord
+          </label>
+          <input
+            class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-200 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
+            id="confirmPassword"
+            type="password"
+          />
+        </div>
+        <div>
+          <label
+            class="text-gray-700 dark:text-gray-200"
+            for="firstName"
+          >
+            Fornavn
+          </label>
+          <input
+            class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-200 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
+            data-test="firstNameTest"
+            id="firstName"
+            type="text"
+          />
+        </div>
+        <div>
+          <label
+            class="text-gray-700 dark:text-gray-200"
+            for="lastName"
+          >
+            Etternavn
+          </label>
+          <input
+            class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-200 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
+            id="lastName"
+            type="text"
+          />
+        </div>
+        <div>
+          <label
+            class="text-gray-700 dark:text-gray-200"
+            for="address"
+          >
+            Addresse
+          </label>
+          <input
+            class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-200 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
+            id="address"
+            type="text"
+          />
+        </div>
+      </div>
+      <div
+        class="flex justify-end mt-6"
+      >
+        <button
+          class="px-6 py-2 leading-5 text-white transition-colors duration-200 transform bg-gray-700 rounded-md hover:bg-gray-600 focus:outline-none focus:bg-gray-600"
+          type="submit"
+        >
+          <div>
+            Lagre
+          </div>
+        </button>
+      </div>
+    </form>
+  </section>
+  <ul
+    data-test="errorMessageList"
+  >
+    <!--v-if-->
+    
+    
+  </ul>
+  
+</div>
+`;
diff --git a/tests/unit/apiutil-login-mock.spec.js b/tests/unit/apiutil-login-mock.spec.js
index b1c99b4c45466356b8b75bb354c1c52253edc156..b6d573beb45aff0450d4d52334a8e69cce950128 100644
--- a/tests/unit/apiutil-login-mock.spec.js
+++ b/tests/unit/apiutil-login-mock.spec.js
@@ -4,42 +4,39 @@ import axios from "axios";
 jest.mock("axios");
 
 describe("testing mocking of apiutil.js", () => {
+
   it("check that login fails with wrong credentials - against mock", async () => {
-    // mock api response on POST call (once)
-    const expectedLoginResponse = { response: "Login failed" };
+
+    const loginRequest = {
+      email: "wrong@email.com",
+      password: "thisiswrong123"};
+
+    const expectedLoginResponse = { isLoggedIn: false, token: "" }
+
     axios.post.mockImplementation(() =>
       Promise.resolve({ data: expectedLoginResponse })
     );
 
-    // do the call
-    const loginRequest = {
-      email: "wrong@email.com",
-      password: "thisiswrong123",
-    };
     const loginResponse = await doLogin(loginRequest);
 
-    //  check response
-    //  note that even if wrong username and password are used, mock is configured to return Success
-    expect(loginResponse).toEqual(expectedLoginResponse);
+    expect(loginResponse.token.isLoggedIn).toEqual(expectedLoginResponse.isLoggedIn);
   });
+
   it("check that login succeeds when correct credentials - against mock", async () => {
-    // mock api response on POST call (once)
-    const apiResponse = {
-      response:
-        "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
-    };
-    const expectedLoginResponse = { response: "Login failed" };
-    axios.post.mockImplementation(() => Promise.resolve({ data: apiResponse }));
 
-    // do the call
     const loginRequest = {
       email: "correct@email.com",
-      password: "thisiscorrect123",
-    };
+      password: "thisiscorrect123"};
+
+    const apiResponse = {isLoggedIn: true, token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM" +
+          "0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"};
+
+    const expectedLoginResponse = {isLoggedIn: false, token: ""};
+
+    axios.post.mockImplementation(() => Promise.resolve({ data: apiResponse }));
+
     const loginResponse = await doLogin(loginRequest);
 
-    //  check response
-    //  note that even if wrong username and password are used, mock is configured to return Success
-    expect(loginResponse).not.toEqual(expectedLoginResponse);
+    expect(loginResponse.token.isLoggedIn).not.toEqual(expectedLoginResponse.isLoggedIn);
   });
 });
diff --git a/tests/unit/apiutil-user-mock.spec.js b/tests/unit/apiutil-user-mock.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..73612f0f3579f5c04b99d2424a1a57fd62ff31bc
--- /dev/null
+++ b/tests/unit/apiutil-user-mock.spec.js
@@ -0,0 +1,28 @@
+import { getUser } from "@/utils/apiutil";
+import axios from "axios";
+
+jest.mock("axios");
+
+describe("testing mocking of apiutil.js", () => {
+  it("check that existing user returns correctly", async () => {
+    const expectedResponse = {
+      response:
+        "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhY2NvdW50X2lkIjoiNiIsImV4cCI6MTY1MTEzMDU2NywiZmlyc3RfbmFtZSI6IkFsaWRhIiwiZW1haWwiOiJhbGlkYUB0ZXN0Lm5vIn0.Cp3_qfLhA55j5yaa1WPG97LNtvAZssxo0ROP3VIrHVs",
+    };
+    axios.get.mockImplementation(() =>
+      Promise.resolve({ data: expectedResponse })
+    );
+
+    const userResponse = await getUser(1);
+    expect(userResponse).not.toEqual({ response: "User not found in DB" });
+  });
+  it("check that non-existing user returns 404", async () => {
+    const expectedResponse = { response: "User not found in DB" };
+    axios.get.mockImplementation(() =>
+      Promise.resolve({ data: expectedResponse })
+    );
+
+    const userResponse = await getUser(100000);
+    expect(userResponse).toEqual(expectedResponse);
+  });
+});
diff --git a/tests/unit/create-new-group.spec.js b/tests/unit/create-new-group.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..2b269b082ece04c8d1cbfa9c8eb9233d0d4e00f8
--- /dev/null
+++ b/tests/unit/create-new-group.spec.js
@@ -0,0 +1,49 @@
+import { shallowMount } from "@vue/test-utils";
+import CreateNewGroup from "@/components/CreateNewGroup.vue";
+
+describe("CreateNewGroup elements rendering", () => {
+
+    it("renders all labels", () => {
+
+        const wrapper = shallowMount(CreateNewGroup);
+
+        expect(wrapper.find('#radioBoxLabel').text()).toMatch("Synlighet");
+        expect(wrapper.find('#radioBoxOpenLabel').text()).toMatch("Ã…pen");
+        expect(wrapper.find('#radioBoxPrivateLabel').text()).toMatch("Privat");
+        expect(wrapper.find('#titleLabel').text()).toMatch("Gruppenavn");
+        expect(wrapper.find('#selectCategoryLabel').text()).toMatch("Kategori");
+        expect(wrapper.find('#descriptionLabel').text()).toMatch("Beskrivelse");
+        expect(wrapper.find('#imageLabel').text()).toMatch("Bilde");
+
+    });
+
+    it("Tests setting values of input field", async() => {
+
+        const wrapper = shallowMount(CreateNewGroup);
+
+        const titleInput = wrapper.find('#title');
+        await titleInput.setValue("Fjellgata");
+        expect(titleInput.element.value).toBe("Fjellgata");
+
+        const selectedCategory = wrapper.find('#categories');
+        await selectedCategory.setValue("Borettslag");
+        expect(selectedCategory.element.value).toBe("Borettslag");
+
+        const descriptionInput = wrapper.find('#description');
+        await descriptionInput.setValue("Dette er et borettslag");
+        expect(descriptionInput.element.value).toBe("Dette er et borettslag");
+    });
+
+    it("Tests if radio box checks", async() => {
+
+        const wrapper = shallowMount(CreateNewGroup);
+
+        const radioInputOpen = wrapper.find('#flexRadioOpen');
+        await radioInputOpen.setChecked();
+        expect(radioInputOpen.element.checked).toBeTruthy();
+
+        const radioInputPrivate = wrapper.find('#flexRadioPrivate');
+        await radioInputPrivate.setChecked();
+        expect(radioInputPrivate.element.checked).toBeTruthy();
+    });
+});
diff --git a/tests/unit/search-item-list.spec.js b/tests/unit/search-item-list.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..6a01bbbdbe83b35b070e3fc9bf8ac9ed061ab6af
--- /dev/null
+++ b/tests/unit/search-item-list.spec.js
@@ -0,0 +1,15 @@
+import { shallowMount } from "@vue/test-utils";
+import SearchItemListComponent from "@/components/SearchItemListComponent.vue";
+
+describe("CreateNewGroup elements rendering", () => {
+
+    it("Tests setting values of input field", async() => {
+
+        const wrapper = shallowMount(SearchItemListComponent);
+
+        const searchInput = wrapper.find('#searchInput');
+        await searchInput.setValue("Dyson");
+        expect(searchInput.element.value).toBe("Dyson");
+
+    });
+});