diff --git a/cypress/e2e/navbar.cy.js b/cypress/e2e/navbar.cy.js
index 2cbd9b1ad9230819d7890632705bb94da06736a4..9e227781986c499d749fd2f66f66d95f56a4ee32 100644
--- a/cypress/e2e/navbar.cy.js
+++ b/cypress/e2e/navbar.cy.js
@@ -1,6 +1,5 @@
 describe('Correct navigation links', () => {
-    /*TODO*/
 })
 describe('Navbar on all pages', () => {
-  /*TODO*/
-})
\ No newline at end of file
+
+})
diff --git a/package-lock.json b/package-lock.json
index 8734150139ece57f5d4421404eef4dbd24eac98a..1a0fb3516a7a9964ae3a16a44de51de879e6b268 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,6 +13,7 @@
         "jwt-decode": "^3.1.2",
         "pinia": "^2.0.35",
         "pinia-plugin-persistedstate": "^3.1.0",
+        "sass": "^1.62.0",
         "vue": "^3.2.45",
         "vue-router": "^4.1.6"
       },
@@ -1444,9 +1445,6 @@
       "version": "3.1.3",
       "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
       "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
       "dependencies": {
         "normalize-path": "^3.0.0",
         "picomatch": "^2.0.4"
@@ -1653,9 +1651,6 @@
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
       "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
       "engines": {
         "node": ">=8"
       }
@@ -1691,9 +1686,6 @@
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
       "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
       "dependencies": {
         "fill-range": "^7.0.1"
       },
@@ -2088,15 +2080,12 @@
       "version": "3.5.3",
       "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
       "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
-      "dev": true,
       "funding": [
         {
           "type": "individual",
           "url": "https://paulmillr.com/funding/"
         }
       ],
-      "optional": true,
-      "peer": true,
       "dependencies": {
         "anymatch": "~3.1.2",
         "braces": "~3.0.2",
@@ -3042,9 +3031,6 @@
       "version": "7.0.1",
       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
       "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
       "dependencies": {
         "to-regex-range": "^5.0.1"
       },
@@ -3164,7 +3150,6 @@
       "version": "2.3.2",
       "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
       "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
-      "dev": true,
       "hasInstallScript": true,
       "optional": true,
       "os": [
@@ -3308,9 +3293,6 @@
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
       "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
       "dependencies": {
         "is-glob": "^4.0.1"
       },
@@ -3598,10 +3580,7 @@
     "node_modules/immutable": {
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz",
-      "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==",
-      "dev": true,
-      "optional": true,
-      "peer": true
+      "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg=="
     },
     "node_modules/imurmurhash": {
       "version": "0.1.4",
@@ -3668,9 +3647,6 @@
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
       "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
       "dependencies": {
         "binary-extensions": "^2.0.0"
       },
@@ -3706,9 +3682,6 @@
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
       "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
       "engines": {
         "node": ">=0.10.0"
       }
@@ -3726,9 +3699,6 @@
       "version": "4.0.3",
       "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
       "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
       "dependencies": {
         "is-extglob": "^2.1.1"
       },
@@ -3762,9 +3732,6 @@
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
       "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
       "engines": {
         "node": ">=0.12.0"
       }
@@ -5074,9 +5041,6 @@
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
       "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
       "engines": {
         "node": ">=0.10.0"
       }
@@ -5329,9 +5293,6 @@
       "version": "2.3.1",
       "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
       "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
       "engines": {
         "node": ">=8.6"
       },
@@ -5715,9 +5676,6 @@
       "version": "3.6.0",
       "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
       "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
       "dependencies": {
         "picomatch": "^2.2.1"
       },
@@ -5919,9 +5877,6 @@
       "version": "1.62.0",
       "resolved": "https://registry.npmjs.org/sass/-/sass-1.62.0.tgz",
       "integrity": "sha512-Q4USplo4pLYgCi+XlipZCWUQz5pkg/ruSSgJ0WRDSb/+3z9tXUOkQ7QPYn4XrhZKYAK4HlpaQecRwKLJX6+DBg==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
       "dependencies": {
         "chokidar": ">=3.0.0 <4.0.0",
         "immutable": "^4.0.0",
@@ -6799,9 +6754,6 @@
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
       "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-      "dev": true,
-      "optional": true,
-      "peer": true,
       "dependencies": {
         "is-number": "^7.0.0"
       },
diff --git a/package.json b/package.json
index 2c3e2f56a6ab229a407cf87679cc88cbc07e31b7..720c8cb46e52d384a27d5f8ae3248efdc7c1a7c4 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
     "jwt-decode": "^3.1.2",
     "pinia": "^2.0.35",
     "pinia-plugin-persistedstate": "^3.1.0",
+    "sass": "^1.62.0",
     "vue": "^3.2.45",
     "vue-router": "^4.1.6"
   },
diff --git a/src/App.vue b/src/App.vue
index 1358b7e3e414d1466e1288bbfed8cdcabdafb3fc..d9988e4a1832293fff956f9976fd7782c97b76ec 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,19 +1,15 @@
 <script setup>
-import { RouterLink, RouterView } from 'vue-router'
-import Navbar from "@/components/Navbar.vue";
-
+  import { RouterView } from 'vue-router'
+  import Navbar from "@/components/Navbar.vue";
 
 </script>
 
 <template>
-    <Navbar></Navbar>
-    <body>
-    <RouterView />
-    </body>
-
+  <Navbar v-if="$route.name !== 'login' && $route.name !== 'selectProfile'" />
+  <RouterView />
 </template>
 
-<style scoped>
+<style lang=scss scoped>
 header {
   line-height: 1.5;
   max-height: 100vh;
@@ -52,7 +48,7 @@ nav a:first-of-type {
   border: 0;
 }
 
-@media (min-width: 1024px) {
+@media (min-width: base.$desktop-min) {
   header {
     display: flex;
     place-items: center;
diff --git a/src/assets/main.css b/src/assets/main.css
index 2d624bc8d97520029335b1976f166e1a46c461b1..c417db8ebe95a78dcdf6bb8c362b0a6cb4dc518b 100644
--- a/src/assets/main.css
+++ b/src/assets/main.css
@@ -25,10 +25,14 @@ a,
   body {
     display: flex;
     place-items: center;
+    justify-content: center;
+    align-items: center;
   }
 
   #app {
     display: grid;
-    padding: 0 2rem;
+    padding: 2rem 2rem;
+
+    
   }
 }
diff --git a/src/components/EditAccount.vue b/src/components/EditAccount.vue
new file mode 100644
index 0000000000000000000000000000000000000000..564f678621ce2e4e4873b4ea42d473d54184630d
--- /dev/null
+++ b/src/components/EditAccount.vue
@@ -0,0 +1,198 @@
+<template>
+    <h2>Konto-innstillinger</h2>
+    <form @submit.prevent="submit">
+        <p class="infoText">OBS: Kontakt admin dersom du ønsker å oppdatere epost</p><br>
+
+        <p id="emailField">Epost: {{this.account.email}}</p><br>
+
+        <label for="fname">Endre fornavn</label><br>
+        <input type="text" id="fname" v-model="updatedAccount.upFirstname"><br>
+
+        <label for="password">Endre passord</label><br>
+        <input type="password" id="password" v-model="updatedAccount.upPassword">
+
+        <button class="greenBtn" @click="saveAccountSettings">Lagre profilendringer</button>
+        <p id="alert">{{alertMsg}}</p>
+    </form>
+
+    <div id="logout">
+        <p class="infoText">Logger deg ut fra din SmartMat-konto</p>
+        <button class ="redBtn" @click="logOut">Logg ut</button>
+    </div>
+
+
+    <br>
+    <br>
+    <hr>
+
+    <form  @submit.prevent="submit" id = "dangerZone">
+        <h1>🔺FARESONE🔺</h1>
+        <p class="infoText">Ved å trykke på knappen nedenfor, vil du slette din SmartMat-konto</p>
+        <input type="checkbox" id="deletionCheckbox" v-model="deletionConfirmation">
+        <label for="deletionCheckbox"> Jeg bekrefter jeg skjønner dette, og ønsker å slette kontoen min SmartMat-konto for alltid.</label><br>
+        <button class="darkRedBtn" id ="delAccount" @click="deleteAccount">SLETT KONTO</button>
+        <p id="alert">{{delAlertMsg}}</p>
+    </form>
+</template>
+
+<script>
+import {mapState, mapStores} from "pinia";
+import {API} from "@/util/API";
+import { useAuthStore } from "@/stores/authStore";
+import router from "../router";
+export default {
+    name: "EditAccount",
+    computed: {
+        ...mapState(useAuthStore, ['account']),
+        ...mapStores(useAuthStore),
+        updatedAccount() {
+            return {
+                upFirstname: this.account.firstname,
+                upPassword:'',
+            }
+        },
+    },
+    data() {
+        return {
+            alertMsg:'', //message at the bottom of the form where you change account firstname and password
+            deletionConfirmation: false,
+            delAlertMsg:'', //message in the 'dager zone'
+        }
+    },
+    methods: {
+        saveAccountSettings(){ //passord
+            const id = this.account.id;
+
+            let newPassword = null
+            let newFirstName = null;
+
+            //checks if username and password have been changed
+            if(this.updatedAccount.upPassword.length!==0) {
+                newPassword = this.updatedAccount.upPassword;
+            }
+            //firstName won't be changed if empty
+            if(this.updatedAccount.upFirstname!==''){
+                newFirstName = this.updatedAccount.upFirstname;
+            }
+
+            API.updateAccount(
+                id,{
+                    firstname:newFirstName,
+                    password:newPassword,
+                }
+            ).then((savedAccount)=>{
+                useAuthStore().setAccount(savedAccount);
+                this.alertMsg = "Konto oppdatert."
+            }).catch(()=> {
+                this.alertMsg = "‼️Det oppsto en feil.‼️ "
+            })
+        },
+        deleteAccount(){
+            if(this.deletionConfirmation===false){
+                this.delAlertMsg = "‼️Du må bekrefte at du vil slette konto ved å huke av boksen‼️"
+            }
+            else {
+                const id = this.account.id;
+                API.deleteAccount(
+                    id
+                ).then(()=>{
+                    router.push('/login')
+                }).catch(()=> {
+                    this.delAlertMsg = "‼️Det oppsto en feil ved sletting av bruker‼️"
+                })
+            }
+        },
+        logOut(){
+            useAuthStore().logout();
+            router.push('/login')
+        },
+    }
+ }
+</script>
+
+<style scoped lang="scss">
+#dangerZone {
+    color: darkred;
+}
+
+#logout{
+    background-color: base.$grey;
+    color: black;
+    padding: 2em;
+    margin-top: 2em;
+    margin-bottom: 2em;
+    display: flex;
+    flex-direction: column;
+}
+
+input[type="checkbox"] {
+    width: 2.5em;
+    height: 2.5em;
+}
+
+
+
+/*--General--*/
+form {
+    background-color: base.$grey;
+    color: black;
+    align-content: end;
+    padding: 2em;
+    margin-top: 2em;
+    margin-bottom: 2em;
+}
+
+input[type="text"],
+input[type="password"]{
+    width: 100%;
+    padding: .5em;
+}
+
+button {
+    color: black;
+    border: 1px solid black;
+    margin: 1em;
+    padding:.9em;
+    font-weight: bold;
+}
+.redBtn {
+    background-color: base.$red;
+    border:none;
+    color:white;
+}
+
+.redBtn:hover {
+    background-color: base.$red-hover;
+}
+
+.darkRedBtn {
+    background-color: darkred;
+    border:none;
+    color:white;
+}
+.darkRedBtn:hover {
+    background-color: base.$darkred-hover;
+}
+
+.greenBtn{
+    background-color: base.$green;
+    border:none;
+    color:white;
+}
+.greenBtn:hover{
+    background-color: base.$green-hover;
+}
+
+.infoText {
+    background-color: white;
+    padding: .5em;
+    margin: .4em;
+}
+
+#alert {
+     display: flex;
+     width:100%;
+     justify-content: center;
+     font-weight: bold;
+ }
+</style>
\ No newline at end of file
diff --git a/src/components/EditProfile.vue b/src/components/EditProfile.vue
new file mode 100644
index 0000000000000000000000000000000000000000..8725cfe22726c81985687fb8185ed436f4f12b77
--- /dev/null
+++ b/src/components/EditProfile.vue
@@ -0,0 +1,262 @@
+<template>
+        <h2>Profilinnstillinger</h2>
+
+
+        <div v-if="hasProfileImage" id = "profilepicture-container">
+            <img  width="100" :src="this.updatedProfile.upImage" alt="profile picture">
+        </div>
+        <div v-else id="#placeholder">
+            <Icon   icon="material-symbols:person" :color=iconColor :style="{ fontSize: '500px'}" />
+        </div>
+
+        <h3>{{this.profile.name}}</h3>
+        <button  @click="changeProfile" id="changeUserBtn" class="redBtn">Bytt bruker</button>
+
+    <form @submit.prevent="submit">
+            <label for="brukernavn">Profilnavn</label><br>
+            <input type="text" required id="brukernavn" v-model="this.updatedProfile.upName"><br>
+            <br>
+            <h3>Brukertype</h3>
+            <input type="radio" id="normal" value="false" name="restrict" v-model="this.updatedProfile.upRestricted">
+            <label for="normal"> Standard</label><br>
+
+            <input type="radio" id="restricted" value="true" name="restrict" v-model="this.updatedProfile.upRestricted">
+            <label for="restricted"> Begrenset - Kan ikke redigere ukeplan eller handleliste</label><br><br>
+
+
+            <h3>Profilbilde</h3><br>
+            <div id="changeUserImage">
+                <div v-if="hasProfileImage" id = "profilepicture-container">
+                    <img width="50" :src="this.updatedProfile.upImage" alt="profile picture">
+                </div>
+                <div v-else id = "profilepicture-container">
+                    <Icon icon="material-symbols:person" :color=iconColor :style="{ fontSize: '30px'}" />
+                </div>
+
+                <label for="chooseImageUrl">Bilde-URL:</label><br>
+                <!--<input type="file" id="chooseImage" v-on:change="updateImage">-->
+                <input type="text" id="chooseImageUrl" v-model="this.updatedProfile.upImage">
+
+            </div>
+        <br><br>
+            <div id = "submitbuttonBox">
+                <button class="greenBtn" @click=" saveUserSettings">Lagre profilendringer</button>
+                <button class="darkRedBtn" @click="deleteProfile">Slett brukerprofil</button>
+            </div>
+
+            <p id="alert">{{alertMsg}}</p>
+
+        </form>
+
+</template>
+
+<script>
+import {mapState, mapStores} from "pinia";
+import {Icon} from "@iconify/vue";
+import {API} from "@/util/API";
+import { useAuthStore } from "@/stores/authStore";
+import router from "../router";
+export default {
+    name: "EditProfile",
+    components: {Icon},
+    data() {
+        return {
+            alertMsg:'',
+            initialName: '', //used to compare with updated values
+            initialRestriction: '',
+        }
+    },
+    computed: {
+        ...mapState(useAuthStore, ['profile']),
+        ...mapStores(useAuthStore),
+        updatedProfile() {
+          return {
+              upName: this.profile.name,
+              upRestricted: this.profile.restricted,
+              upImage: this.profile.profileImageUrl,
+          }
+        },
+        iconColor() {
+            return "#D9D9D9"
+        },
+        hasProfileImage() {
+            return false;
+        }
+    },
+    beforeMount() {//used to compare with changed values
+        this.initialName = this.profile.name;
+        this.initialRestriction = this.profile.restricted;
+    },
+    methods: {
+        changeProfile(){
+            router.push("/selectProfile");
+        },
+        async deleteProfile() {
+                const id = this.profile.id;
+                API.deleteProfile(id).then(() => {
+                    router.push('/selectProfile')
+                }).catch((_) => {
+                    this.alertMsg = "‼️Alle kontoer må ha minst en profil (profil ble ikke slettet)‼️"
+                })
+        },
+        saveUserSettings(){
+            const id = this.profile.id;
+
+            let newName = null;
+            let newRestricted = null;
+
+            if(this.updatedProfile.upName !== this.initialName){
+                newName = this.updatedProfile.upName
+            }
+            if(this.updatedProfile.upRestricted !== this.initialRestriction){
+                newRestricted = this.updatedProfile.upRestricted
+            }
+
+            API.updateProfile(
+                id,{
+                    name:newName,
+                    profileImageUrl:this.updatedProfile.upImage,
+                    isRestricted: newRestricted,
+                }
+            ).then((savedProfile)=>{
+                useAuthStore().setProfile(savedProfile);
+                this.alertMsg = "Profil oppdatert."
+            }).catch(error=> {
+                console.log(error)
+                if (error.message === '400') {
+                    if(newRestricted){
+                        this.alertMsg = '‼️Det oppsto en feil: Sørg for at det finnes mist en standard profil på kontoen‼️ '
+                    } else if(this.updatedProfile.name !== this.initialName || this.updatedProfile.name) {
+                        this.alertMsg = '‼️Det oppsto en feil: Det finnes allerede en bruker med samme navn‼️'
+                    }
+                }else{
+                    this.alertMsg = "‼️Det oppsto en feil.‼️"
+                }
+            })
+        },
+
+
+
+
+
+        updateImage(){
+            //todo update image preview
+        },
+        chooseProfilePicture(){
+            this.alertMsg = "skriv inn bildelenke i feltet, og oppdater innstillinger"
+        },
+    }
+}
+
+</script>
+
+<style scoped lang="scss">
+
+input[type="radio"] {
+  width: 2em;
+  height: 2em;
+
+}
+
+#changeUserBtn {
+  border: 1px solid black;
+}
+
+#profilepicture-container {
+  display:flex;
+  border-radius:50%;
+  width:100px;
+  height: 100px;
+  background-color: white;
+  justify-content: center;
+  align-items: center;
+  border: 3px solid base.$grey;
+}
+
+#changeUserImage {
+    display:flex;
+}
+
+img {
+  border-radius: 50%;
+}
+
+#changeUserImage #profilepicture-container {
+    width: 50px;
+    height: 50px;
+}
+
+#submitbuttonBox {
+    display:flex;
+    justify-content: space-between;
+}
+
+
+
+
+
+/*--General--*/
+form {
+   background-color: base.$grey;
+   color: black;
+   align-content: end;
+   padding: 2em;
+   margin-top: 2em;
+   margin-bottom: 2em;
+ }
+
+input[type="text"],
+input[type="password"]{
+  width: 100%;
+  padding: .5em;
+}
+
+button {
+  color: black;
+  border: 1px solid black;
+  margin: 1em;
+  padding:.9em;
+  font-weight: bold;
+}
+.redBtn {
+  background-color: base.$red;
+  border:none;
+  color:white;
+}
+
+.redBtn:hover {
+  background-color: base.$red-hover;
+}
+
+.darkRedBtn {
+  background-color: darkred;
+  border:none;
+  color:white;
+}
+.darkRedBtn:hover {
+  background-color: base.$darkred-hover;
+}
+
+.greenBtn{
+  background-color: base.$green;
+  border:none;
+  color:white;
+}
+.greenBtn:hover{
+  background-color: base.$green-hover;
+}
+
+.infoText {
+  background-color: white;
+  padding: .5em;
+  margin: .4em;
+}
+
+#alert {
+  display: flex;
+  width:100%;
+  justify-content: center;
+  color: base.$light-green;
+  font-weight: bold;
+}
+</style>
\ No newline at end of file
diff --git a/src/components/FridgeItem.vue b/src/components/FridgeItem.vue
index d259d5db29f607aa03b9464483dd6c51132e4164..a23603f03c0e965368cda1ebea78fdf8865bb36f 100644
--- a/src/components/FridgeItem.vue
+++ b/src/components/FridgeItem.vue
@@ -2,7 +2,9 @@
 <div id ="item">
     <img :src="getImage" alt="">
     <div id="itemInfo">
-        <p id="fridgeItemName">{{this.actualItem.item.name }} {{ this.actualItem.amount.quantity }}{{this.actualItem.item.amount.unit}}</p>
+        <p id="fridgeItemName">{{ this.fridgeItem.item.name }} {{
+                this.fridgeItem.amount.quantity
+            }}{{ this.fridgeItem.item.amount.unit }}</p>
         <p class="expText" :style="{color:expirationTextColor}">{{expirationText}}</p>
     </div>
     <div id = "appleBtn" @click="appleBtnPressed">
@@ -10,7 +12,6 @@
     </div>
 
 </div>
-    <hr>
 </template>
 
 <script>
@@ -36,7 +37,7 @@ export default {
             }
         },
         getImage(){
-            return this.actualItem.item.image_url;
+            return this.fridgeItem.item.image_url;
 
         },
         expirationText() {
@@ -66,11 +67,7 @@ export default {
         }
     },
     props: {
-        item: {
-          type:Object,
-          required: false,
-        },
-        actualItem: {
+        fridgeItem: {
             type: Object,
             required:false,
         },
@@ -82,7 +79,7 @@ export default {
     },
     methods: {
         getDateDifference(){ //returns the difference in days between the expiration date and today
-            let date = this.actualItem.exp_date;
+            let date = this.fridgeItem.exp_date;
             const epDate = new Date(date);
 
             const parsedDate = Date.parse(epDate)
@@ -94,10 +91,10 @@ export default {
             return numOfDays;
         },
       appleBtnPressed(){
-          this.$emit('appleBtnPressed', this.actualItem);
+          this.$emit('appleBtnPressed', this.fridgeItem);
       },
         formatDate(){ //formats expiration date as dd.mm.yyyy
-            let fullExpirationDate = new Date(this.actualItem.exp_date);
+            let fullExpirationDate = new Date(this.fridgeItem.exp_date);
             let day = fullExpirationDate.getDate();
             let month= (fullExpirationDate.getMonth()+1).toString();
             let year= fullExpirationDate.getFullYear().toString();
@@ -112,13 +109,17 @@ export default {
 #item {
     background-color: base.$white;
     color: black;
-    qborder-radius: 10px;
     padding: 1em;
     padding-left: 2em;
     padding-right:2em;
     display:flex;
     align-items: center;
     justify-content: space-between;
+    border-bottom: solid 1px base.$grey;
+}
+
+#item:last-child {
+    border-bottom: none;
 }
 
 #fridgeItemName {
diff --git a/src/components/GroceryOffers.vue b/src/components/GroceryOffers.vue
index c970238dc31d8463b342f7f404db08c9988d6014..cbc668647d78b1a3fae6125cd7f1c68dceb2c945 100644
--- a/src/components/GroceryOffers.vue
+++ b/src/components/GroceryOffers.vue
@@ -1,6 +1,6 @@
 <template>
     <div>
-        <h2>Tilbudaviser</h2>
+        <h2>Lenker til tilbudsaviser</h2>
     </div>
 
   <div id="list">
diff --git a/src/components/ItemSearch.vue b/src/components/ItemSearch.vue
index cfa6e6c5d551e11c2a17317003dafdd9055ef909..10805ce1e1e4a2edb9f9eeda83e3e4b11650ac73 100644
--- a/src/components/ItemSearch.vue
+++ b/src/components/ItemSearch.vue
@@ -1,9 +1,9 @@
 <template>
     <div v-if="showSearch" id="wrapper">
-        <h3>SØK ETTER VARE</h3>
+        <h3>Søk etter vare</h3>
         <div id="searchBoxDiv">
             <input type="text" id="searchBox" v-model="itemSearch">
-            <button @click="search">Søk</button>
+            <button id="search-button" @click="search">Søk</button>
         </div>
 
         <p>Resultater: ({{searchResult.length}})</p>
@@ -12,9 +12,10 @@
             <option v-for ="item in searchResult" :value="item" :key="item.ean">{{item.name}} ({{item.amount.quantity}}{{item.amount.unit}})</option>
         </select>
         <p>Antall varer: <span v-if="numOfItemsToAdd>1 && selectedItem!=null">(totalt: {{this.totalNumOfItems}} {{selectedItem.amount.unit}})</span></p>
-        <input type="number" min='1' v-model="numOfItemsToAdd"><br>
+        <input id="items-input" type="number" min='1' v-model="numOfItemsToAdd"><br>
 
-        <button id = "addToFridgeBtn" @click="addToFridge">Legg i kjøleskap</button>
+        <button v-if="addsToFridge" id = "addToFridgeBtn" @click="addToFridge">Legg i kjøleskap</button>
+        <button v-else id = "addToFridgeBtn" @click="addToShoppingList">Legg i handleliste</button>
 
 
     </div>
@@ -22,10 +23,17 @@
 
 <script>
 import {API} from "@/util/API";
+import { useAuthStore } from "@/stores/authStore.js";
 
 
 export default {
     name: "itemSearch",
+    props: {
+        addsToFridge: {
+            type: Boolean,
+            default: false
+        }
+    },
     data(){
         return{
             itemSearch:'',
@@ -55,7 +63,25 @@ export default {
                         {
                             "quantity": this.selectedItem.amount.quantity*num,
                             "unit": this.selectedItem.amount.unit}}
-            ).then(() => this.$emit('itemsAdded',this.selectedItem)).catch((_)=> console.log("No items were added to the fridge"))
+            ).then((_) => {
+                this.$emit('itemsAdded',this.selectedItem)
+            }).catch((_)=> console.log("No items were added to the fridge"))
+        },
+        async addToShoppingList() {
+            const num = this.numOfItemsToAdd;
+            const authStore = useAuthStore();
+
+            if (authStore.profile.restricted) {
+                await API.addSuggestion(this.selectedItem.id, num)
+                    .then((ingredient) => {this.$emit('itemsAdded', ingredient)})
+                    .catch(err => console.log(err));
+            } else {
+                await API.addItemToShoppingList(this.selectedItem.id, num)
+                    .then((ingredient) => {
+                        console.log(ingredient)
+                        this.$emit('itemsAdded', ingredient)
+                    }).catch(err => console.log(err));
+            }
         }
     }
 }
@@ -74,6 +100,14 @@ select {
 
 }
 
+#items-input {
+    margin-bottom: 1em;
+}
+
+#search-button {
+    margin-left: 0.5em;
+}
+
 #searchBoxDiv {
     display:flex;
     width:100%;
@@ -91,14 +125,17 @@ button {
     padding: .5em;
     background-color: base.$light-green;
     border-radius: 5%;
-
+    background-color: base.$green;
+    color: white;
+    font-weight: bold;
     border: 1px solid base.$green;
+    height: 30px;
 
 }
 
 button:hover {
     border: 1px solid base.$grey;
-    background-color: base.$light-green-hover;
+    background-color: base.$light-green;
     cursor: pointer;
 
 
diff --git a/src/components/Navbar.vue b/src/components/Navbar.vue
index 4936528217a92b213a2e8391ad76ff6703b9ec0e..b0e13c362fcafcc7002a5b1e5e13fe9ac110ba6a 100644
--- a/src/components/Navbar.vue
+++ b/src/components/Navbar.vue
@@ -18,13 +18,13 @@
                     </RouterLink>
                 </li>
                 <li>
-                    <RouterLink :to="'/'" :aria-label="'link to shopping list'">
+                    <RouterLink :to="'/shoppingList'" :aria-label="'link to shopping list'">
                       <Icon icon="material-symbols:event-list-outline" :color="iconColor" :style="{ fontSize: iconSize }" />
                     </RouterLink>
                 </li>
                 <li>
-                    <RouterLink :to="'/'" :aria-label="'link to settings page'">
-                      <Icon icon="mdi:cog" :color="iconColor" :style="{ fontSize: iconSize }"/>
+                    <RouterLink :to="'/profileSettings'" :aria-label="'link to settings page'">
+                      <Icon id="settingsIcon" icon="mdi:cog" :color="iconColor" :style="{ fontSize: iconSize }"/>
                     </RouterLink>
                 </li>
             </ul>
@@ -34,7 +34,6 @@
 <script>
 import { Icon } from '@iconify/vue';
 import Logo from "@/components/Logo.vue";
-import { RouterLink } from 'vue-router'
 
 export default {
     name: "Navbar",
@@ -46,6 +45,9 @@ export default {
     iconSize() {
       return `32px`;
     },
+    logoSize() {
+      return '52px';
+    }
   }
 }
 </script>
diff --git a/src/components/ShoppingListItem.vue b/src/components/ShoppingListItem.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e69e730e4f3910a5c67711a2320c95eca2a82b84
--- /dev/null
+++ b/src/components/ShoppingListItem.vue
@@ -0,0 +1,166 @@
+<template>
+    <div class="content">
+        <div class="item">
+            <div class="check">
+                <input v-model="isChecked" @click="this.updateChecked()" class="checkbox" type="checkbox">
+            </div>
+
+            <p> {{ this.index }}</p>
+
+            <div class="item-label">
+                <label for="checkbox" class="checkbox-label">{{ this.amount }}x {{ this.itemName }}</label>
+            </div>
+        </div>
+     
+        <div class="delete">
+            <img @click="deleteItem" src="./icons/trash.svg" alt="delete">
+        </div>
+    </div>
+</template>
+
+<script>
+    let uuid = 0;
+
+    export default {
+        beforeCreate() {
+            this.uuid = uuid.toString();
+            console.log(this.itemName + " + " + this.uuid)
+
+            uuid += 1;
+        },
+
+
+        name: "ShoppingListItem",
+        props: {
+            itemName: {
+                type: String,
+                default: "",
+                required: true
+            },
+            amount: {
+                type: Number,
+                default: 1,
+                required: false
+            },
+            propValue: {
+                type: Boolean,
+                default: false,
+                required: false
+            },
+            index: {
+                type: Number,
+                required: true
+
+            }
+        },
+        data() {
+            return {
+                isChecked: this.propValue,
+                uuid: ""
+            }
+        },
+        methods: {
+            updateChecked() {
+                this.$emit('updateItem', {id: this.uuid, isChecked: !this.isChecked})
+            }
+        }
+
+
+    }
+</script>
+
+<style lang="scss" scoped>
+
+    .content {
+        display: flex;
+        flex-direction: row;
+        gap: 10px;
+        justify-content: space-between;
+        background-color: white;
+        padding: 5px;
+        border-top-right-radius: 10px;
+        border-top-left-radius: 10px;
+        //border-bottom: base.$grey solid 1px;
+
+    }
+
+    .content:not(:first-child) {
+        border-radius: 0px;
+    }
+
+    .content:last-child {
+        border-radius: 0px;
+        border-bottom-left-radius: 10px;
+        border-bottom-right-radius: 10px;
+    }
+
+    .content:not(:last-child)::after {
+        content: '';
+        height: 1px; /* this works like a border-width */
+        width: 70%; /* percentage of border shown */
+        background: base.$grey; /* the color of border */
+        position: absolute;
+        bottom: 0;
+        margin: 0 auto; left: 0; right: 0; /* horizontal centering */
+    }
+
+    .item {
+        display: flex;
+        flex-direction: row;
+        gap: 10px;
+    }
+
+    input[type="checkbox"] {
+        -webkit-appearance: none;
+        -moz-appearance: none;
+        appearance: none;
+        width: 35px;
+        height: 35px;
+        border-radius: 50%;
+        border: 2px solid #ccc;
+        
+    }
+
+    input[type="checkbox"]:checked {
+        background-color: base.$light-green;
+    }
+
+    input[type="checkbox"]:checked:after {
+        content: "\2713"; /* Unicode code for checkmark symbol */
+        font-size: 24px;
+        font-weight: bold;
+        color: white;
+        text-align: center;
+        line-height: 35px;
+        position: absolute;
+        left: 50%;
+        top: 50%;
+        transform: translate(-50%, -50%);
+    }
+
+    label {
+        font-size: 20px;
+    }
+
+    img {
+        width: 30px;
+        height: 30px;
+        padding: 5px;
+
+        max-height: 100%;
+        max-width: 100%;
+        
+    
+    }
+
+    .check {
+        display: flex;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .delete {
+        align-self: flex-end;
+    }
+
+</style>
\ No newline at end of file
diff --git a/src/components/__tests__/EditAccount.spec.js b/src/components/__tests__/EditAccount.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..994d431aa651c86b61e34d0a430cf959a6ea0350
--- /dev/null
+++ b/src/components/__tests__/EditAccount.spec.js
@@ -0,0 +1,47 @@
+import {describe, it, expect, vi} from 'vitest'
+import { mount } from '@vue/test-utils'
+import EditAccount from "@/components/EditAccount.vue";
+import {createTestingPinia} from "@pinia/testing";
+import {useAuthStore} from "@/stores/authStore";
+describe('Behaves as expected', () => {
+    const wrapper = mount(EditAccount, {
+        global: {
+            plugins: [createTestingPinia({
+                createSpy: vi.fn,
+            })],
+        },
+    });
+
+    const store = useAuthStore()
+
+    store.account = {
+        id: "1",
+        email:"epost@epost.no",
+        firstname:"Ola",
+        password: "Ola123",
+        fridge: {},
+    }
+
+    it('Has email field that contains the account email', async () => {
+        expect(wrapper.find('#emailField').text()).toContain('epost@epost.no');
+    })
+
+    it('Has firstname field with current firstname', async () => {
+        expect(wrapper.vm.updatedAccount.upFirstname).to.equal('Ola');
+        const fnameInput = wrapper.find('#fname');
+        expect(fnameInput.element.value).to.equal('Ola');
+    })
+
+    it('Password field is empty', async () => {
+        const passwordInput = wrapper.find('#password');
+        expect(passwordInput.element.value).to.equal('');
+    })
+
+    it('attempting to delete account without checking box results in error message', async () => {
+        await wrapper.find('#delAccount').trigger('click');
+        const alertMsg = wrapper.vm.delAlertMsg;
+        expect(alertMsg).to.contain('boks');
+
+    })
+
+})
diff --git a/src/components/__tests__/EditProfile.spec.js b/src/components/__tests__/EditProfile.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..f78db12586fa2a935f9067aba276d8dbfa1e8cf3
--- /dev/null
+++ b/src/components/__tests__/EditProfile.spec.js
@@ -0,0 +1,64 @@
+import { mount } from '@vue/test-utils'
+import { describe, it, expect, vi } from 'vitest'
+import { createTestingPinia } from '@pinia/testing'
+import {useAuthStore} from "@/stores/authStore";
+import EditProfile from '@/components/EditProfile.vue'
+describe('EditProfile', () => {
+    const pinia = createTestingPinia({
+        initialState: {
+            profile: { name: 'Ola',restricted:false,profileImageUrl:"some/valid/image.png" },
+        },
+        createSpy: vi.fn(),
+    })
+
+    const wrapper = mount(EditProfile, {
+        global: {
+            plugins: [pinia],
+        },
+    })
+
+    const store = useAuthStore(pinia)
+    store.profile = {
+        name:"Ola",
+        restricted:true,
+        profileImageUrl:"some/valid/image.png"
+    }
+
+    it('Profile name is on profile page', () => {
+        expect(wrapper.vm.updatedProfile.upName).toContain('Ola')
+        const unameInput = wrapper.find('#brukernavn');
+        expect(unameInput.element.value).to.contain('Ola');
+    })
+
+    it('If profile.restricted is true, then radio input with value false is not selected', () => {
+        const radioInput = wrapper.find('input[type=radio][value="false"]')
+        expect(radioInput.element.checked).toBe(false)
+    })
+
+    it('If profile.restricted is true, then radio input with valuetrue *is* selected', () => {
+        const radioInput = wrapper.find('input[type=radio][value="true"]')
+        expect(radioInput.element.checked).toBe(true)
+    })
+
+    //update the value from restricted true -> false
+    it('After changing restricted radio, the values are updated too', async () => {
+        const notRestrictedRadioInput = wrapper.find('#normal')
+        const restrictedRadioInput = wrapper.find('#restricted')
+
+        expect(notRestrictedRadioInput.element.checked).toBe(false)
+        expect(restrictedRadioInput.element.checked).toBe(true)
+
+        await notRestrictedRadioInput.trigger('click')
+
+        expect(notRestrictedRadioInput.element.checked).toBe(true)
+        expect(restrictedRadioInput.element.checked).toBe(false)
+
+        await wrapper.vm.$nextTick()
+
+        setTimeout(() => {
+            expect(wrapper.vm.updatedProfile.upRestricted).toBe(false)
+        }, 1000);
+    })
+
+
+})
\ No newline at end of file
diff --git a/src/components/__tests__/FridgeItem.spec.js b/src/components/__tests__/FridgeItem.spec.js
index 5a7b241b63107426dc1f3aad53e793c412764e74..2760bed18450440eafcbaac7a8dc29823a0235b3 100644
--- a/src/components/__tests__/FridgeItem.spec.js
+++ b/src/components/__tests__/FridgeItem.spec.js
@@ -28,7 +28,7 @@ describe('Fridge items render correctly', () => {
     it('displays the name of the item', () => {
         const wrapper = mount(FridgeItem, {
             props: {
-                actualItem: normalItem,
+                fridgeItem: normalItem,
             },
         });
         expect(wrapper.text()).toContain('eple');
@@ -37,7 +37,7 @@ describe('Fridge items render correctly', () => {
     it('displays the amount of the item in the fridge' , () => {
         const wrapper = mount(FridgeItem, {
             props: {
-                actualItem: normalItem,
+                fridgeItem: normalItem,
             },
         });
         expect(wrapper.text()).toContain('6');
@@ -46,7 +46,7 @@ describe('Fridge items render correctly', () => {
 
     it('displays item image', () => {
         const wrapper = mount(FridgeItem, {props: {
-                actualItem: normalItem,
+                fridgeItem: normalItem,
             },
         });
         const itemImage = wrapper.find('img');
@@ -58,7 +58,7 @@ describe('Fridge items render correctly', () => {
     it('displays text of different color when item has expired', () => {
         const wrapper = mount(FridgeItem, {
             props: {
-                actualItem: expiredItem,
+                fridgeItem: expiredItem,
             },
         });
 
@@ -71,7 +71,7 @@ describe('Behaves as expected', () => {
     it('emits when the apple button is pressed', async () => {
         const wrapper = mount(FridgeItem, {
             props: {
-                actualItem: normalItem,
+                fridgeItem: normalItem,
             },
         });
 
diff --git a/src/components/__tests__/ShoppingListItem.spec.js b/src/components/__tests__/ShoppingListItem.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..8d61f2b68f7ed420666faf8e071de41c9191fd22
--- /dev/null
+++ b/src/components/__tests__/ShoppingListItem.spec.js
@@ -0,0 +1,23 @@
+import { describe, it, expect, vi} from 'vitest'
+import { createTestingPinia } from '@pinia/testing'
+import { mount } from '@vue/test-utils'
+import ShoppingListItem from "@/components/ShoppingListItem.vue";
+
+
+
+describe('ShoppingListItem', () => {
+    it('mounts correctly', () => {
+        const wrapper = mount(ShoppingListItem, {
+            global: {
+              plugins: [createTestingPinia({
+                createSpy: vi.fn,
+              })],
+            },
+            props: {
+              itemName: "Test",
+              amount: 99
+            }
+          })
+        expect(wrapper.text()).toMatch("99x Test")
+    })
+})
diff --git a/src/components/icons/tips.png b/src/components/icons/tips.png
new file mode 100644
index 0000000000000000000000000000000000000000..7547b26b1bcbb2f138729714bd68dd5b20c5be29
Binary files /dev/null and b/src/components/icons/tips.png differ
diff --git a/src/components/icons/trash.svg b/src/components/icons/trash.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d6a7d41dcee741cd4596a2738a0e4fa5b7b70440
--- /dev/null
+++ b/src/components/icons/trash.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Outline" viewBox="0 0 24 24" width="512" height="512"><path d="M21,4H17.9A5.009,5.009,0,0,0,13,0H11A5.009,5.009,0,0,0,6.1,4H3A1,1,0,0,0,3,6H4V19a5.006,5.006,0,0,0,5,5h6a5.006,5.006,0,0,0,5-5V6h1a1,1,0,0,0,0-2ZM11,2h2a3.006,3.006,0,0,1,2.829,2H8.171A3.006,3.006,0,0,1,11,2Zm7,17a3,3,0,0,1-3,3H9a3,3,0,0,1-3-3V6H18Z"/><path d="M10,18a1,1,0,0,0,1-1V11a1,1,0,0,0-2,0v6A1,1,0,0,0,10,18Z"/><path d="M14,18a1,1,0,0,0,1-1V11a1,1,0,0,0-2,0v6A1,1,0,0,0,14,18Z"/></svg>
diff --git a/src/components/images/w66XcIlw.jpeg b/src/components/images/w66XcIlw.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..f27be0d3372e38997dea9ea9913ad851e4f59048
Binary files /dev/null and b/src/components/images/w66XcIlw.jpeg differ
diff --git a/src/router/index.js b/src/router/index.js
index 3a40bee87c2f0a16bdc65b2cd7b59ae81b1fe2ad..8d1e93cb3e0897934d204e12c3ee786414fea273 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,13 +1,17 @@
 import { createRouter, createWebHistory } from 'vue-router'
+import ProfileSettings from "@/views/SettingsView.vue";
+import MissingPage from "@/views/MissingPage.vue";
 import HomeView from '../views/HomeView.vue'
 import LoginView from '../views/LoginView.vue'
 import SelectProfileView from '../views/SelectProfileView.vue'
 import ProfileCreationView from '../views/ProfileCreationView.vue'
 import RegisterAccountView from '../views/RegisterAccountView.vue'
 import PlannerView from '../views/PlannerView.vue'
-
+import PinCodeView from "@/views/PinCodeView.vue";
 import FridgeView from "@/views/FridgeView.vue";
+import RecipeView from "@/views/RecipeView.vue";
 
+import ShoppingListView from '../views/ShoppingListView.vue'
 
 const router = createRouter({
   history: createWebHistory(import.meta.env.BASE_URL),
@@ -37,6 +41,11 @@ const router = createRouter({
       name: 'registerAccount',
       component: RegisterAccountView
     },
+    {
+      path: '/pincode',
+      name: 'pincode',
+      component: PinCodeView
+    },
     {
       path: '/myFridge',
       name: 'myFridge',
@@ -47,6 +56,26 @@ const router = createRouter({
       name: 'planner',
       component: PlannerView
     },
+    {
+      path: '/recipe/:id',
+      name: 'recipe',
+      component: RecipeView
+    },
+    {
+      path: '/shoppingList',
+      name: 'shoppingList',
+      component: ShoppingListView
+    },
+    {
+      path: '/profileSettings',
+      name: 'profileSettings',
+      component: ProfileSettings
+    },
+    {
+      path: '/:catchAll(.*)',
+      name: "404 Page not found" ,
+      component: MissingPage 
+    }
   ]
 })
 
diff --git a/src/stores/authStore.js b/src/stores/authStore.js
index 70f611f62d6072269cf375c59fd42826cc0c2ca0..db029beb454bad9b49dcfc0c1ac658915888f9fa 100644
--- a/src/stores/authStore.js
+++ b/src/stores/authStore.js
@@ -5,7 +5,9 @@ export const useAuthStore = defineStore("auth", {
       token: "",
       account: {},
       profile: {},
-      profiles: []
+      profiles: [],
+      items: {ingredientList: [], suggestionList: []},
+      fridgeItems: [],
     };
   },
   persist: {
@@ -31,6 +33,23 @@ export const useAuthStore = defineStore("auth", {
     },
     setProfiles(profiles) {
       this.profiles = profiles;
+    },
+    setItems(items) {
+      this.items = items;
+    },
+    setItem(item) {
+      this.items.push(item);
+    },
+    setFridge(fridgeItems){
+      this.fridgeItems = fridgeItems;
+    },
+    addItemToFridge(fridgeItem){
+      this.fridgeItems.push(fridgeItem);
+    },
+    updateProfile(name, image, isRestricted){
+      this.profile.name = name;
+      this.profile.profileImageUrl = image;
+      this.profile.restricted = isRestricted;
     }
   }
 });
diff --git a/src/stores/useFoodPreferenceStore.js b/src/stores/useFoodPreferenceStore.js
new file mode 100644
index 0000000000000000000000000000000000000000..028f2cd981f181f9eeb5b4c6a22403e11e9130e4
--- /dev/null
+++ b/src/stores/useFoodPreferenceStore.js
@@ -0,0 +1,21 @@
+import {API} from "@/util/API"
+import { defineStore} from "pinia";
+
+export const useFoodPreferenceStore = defineStore("foodPreference", {
+    state: () => {
+        return {
+            foodPreferences: [],
+        };
+    },
+    persist: {
+        storage: localStorage,
+    },
+    actions: {
+        fetchAllOptions() {
+            API.getFoodpreferences()
+                .then((foodPreferences) => {
+                    this.foodPreferences = foodPreferences;
+                })
+        }
+    }
+})
\ No newline at end of file
diff --git a/src/style.scss b/src/style.scss
index be108e19e2e37d5a2820357a57bfa434a8d9c681..5ac9953401629264b13437d6b2b770dff15f03a2 100644
--- a/src/style.scss
+++ b/src/style.scss
@@ -1,14 +1,49 @@
 /*APP COLORS*/
 $green: #00663C;
 $light-green: hsla(160, 100%, 37%, 1);
-$white: #FFFFFF;
-$grey: #D9D9D9;
-$red: #EE6D6D;
+$white:#FFFFFF;
+$grey:#D9D9D9;
+$light-grey: #F3F4F9;
+$red:#EE6D6D;
+$darkred: darkred;
 
-$red-hover: darken($red, 5%);
-$green-hover: darken($green, 8%);
-$light-green-hover: darken($light-green, 10%);
+$red-hover: darken( $red, 5% );
+$green-hover: darken( $green, 8% );
+$light-green-hover: darken( $light-green, 10% );
+$darkred-hover: darken(darkred, 10%);
+$indigo: #2c3e50;
 
-
-$desktop-min: 800px;
+$desktop-min: 1024px;
 $phone-min : 360px;
+
+.add-button {
+    border-radius: 50%;
+    border-style: none;
+    width: 70px;
+    height: 70px;
+    font-size: 60px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background-color: $light-green;
+    color: white;
+    transition: .25s ease-in-out;
+    line-height: 1;
+    padding: 0;
+}
+
+.add-button:hover {
+    background-color: $green;
+}
+
+.plus-sign:before {
+  content: '\FF0B';
+}
+.plus-sign {
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  width: 100%;
+  margin: 0;
+  height: 100%;
+}
diff --git a/src/util/API.js b/src/util/API.js
index d156d481b691768a0403d48630ed0e1d845b80ba..48507b710f51989fa41da77523087c1abb8abe0f 100644
--- a/src/util/API.js
+++ b/src/util/API.js
@@ -64,15 +64,23 @@ export const API = {
       });
   },
 
-  // Sends the user into the home page logged in as the profile they clicked on
+
+  /**
+     * Sends the user into the home page logged in as the profile specified
+     * @param id ID of the profile that the user will log in as
+     */
   selectProfile: async (id) => {
     const authStore = useAuthStore()
     return axios.get(`${import.meta.env.VITE_BACKEND_URL}/profile/${id}`, {
       headers: { Authorization: `Bearer ${authStore.token}` },
     })
       .then((response) => {
-        authStore.setProfile(response.data)
-        router.push("/")
+          authStore.setProfile(response.data)
+          if (!response.data.restricted) {
+              router.push('pincode')
+          } else {
+              router.push("/")
+          }
 
       })
       .catch(() => {
@@ -82,7 +90,7 @@ export const API = {
 
   /**
    * Upload profile image
-   * 
+   *
    * @param {Blob} image - the image file contents to upload. Must be a JPEG no bigger than 512kB
    * @param {Number} profileId - the ID of the profile to upload this image to
    * @returns {Promise<String>} A Promise that resolves to the URL of the uploaded image
@@ -109,7 +117,7 @@ export const API = {
 
   /**
    * Sends a request to create a new profile on the currently logged in account
-   * 
+   *
    * @typedef {{name: string, id?: number, accountId?: number, profileImageUrl: string, isRestricted: boolean}} ProfileType
    * @param {ProfileType} profile  - the partial data of profile to create
    * @returns {Promise<ProfileType>} the full profile after saving, with id and account ID set
@@ -130,12 +138,14 @@ export const API = {
       })
   },
 
-  // Returns all profiles to the logged in user
-  getProfiles: async () => {
-    const authStore = useAuthStore();
-    if (!authStore.isLoggedIn) {
-      throw new Error();
-    }
+    /**
+     * @returns all profiles to the logged in user
+     */
+    getProfiles: async () => {
+        const authStore = useAuthStore();
+        if (!authStore.isLoggedIn) {
+            throw new Error();
+        }
 
     return axios.get(import.meta.env.VITE_BACKEND_URL + '/profile', {
       headers: { Authorization: "Bearer " + authStore.token },
@@ -148,10 +158,12 @@ export const API = {
       });
   },
 
-  // Registers a new account and logs into it
-  addAccount: async (request) => {
-    const authStore = useAuthStore();
-
+    /**
+     * Registers a new account and logs into it
+     * @param email the email of the new account
+     * @param password the password of the new account
+     */
+    addAccount: async (request) => {
         axios.post(import.meta.env.VITE_BACKEND_URL + '/account', request)
         .then(() => {
             API.login({email: request.email, password: request.password})
@@ -171,6 +183,7 @@ export const API = {
             headers: { Authorization: `Bearer ${authStore.token}` },
         })
             .then((response) => {
+                authStore.setFridge(response.data)
                 return response.data;
             }).catch(() => {
                 throw new Error("Could not fetch fridge items");
@@ -183,11 +196,11 @@ export const API = {
      * @returns {Promise<void>}
      */
     addToFridge: async(request) =>{
-
         const authStore = useAuthStore();
         axios.post(`${import.meta.env.VITE_BACKEND_URL}/fridge/items`, request,{
             headers: { Authorization: `Bearer ${authStore.token}` },
         }).then((response) => {
+            authStore.setFridge(response.data)
             return response.data;
         }).catch(()=> {
             throw new Error("Could not add item to fridge: ");
@@ -244,19 +257,243 @@ export const API = {
         })
     },
 
+    /**
+     * Getter for the shopping list of a logged in account
+     * @returns a promise that resolves to an array of Ingredient objects representing the shopping list, or an error if it fails
+     */
+    getShoppingList: async () => {
+      const authStore = useAuthStore();
+
+      return axios.get(import.meta.env.VITE_BACKEND_URL + '/shoppinglist',
+      {
+        headers: { Authorization: "Bearer " + authStore.token },
+      })
+      .then((response) => {
+        authStore.setItems(response.data)
+        return response.data
+      })
+      .catch(() => {throw new Error()})
+    },
+
+
+    /**
+     * Adds an item to the logged in account's shopping list
+     * @param itemId the id of the item that will be added
+     * @param amount the amount of the specified item that will be added
+     */
+    addItemToShoppingList: async (itemId, amount) => {
+      const authStore = useAuthStore();
+      return axios.put(import.meta.env.VITE_BACKEND_URL + '/shoppinglist/items/' + itemId + '/' + amount, "",
+      {
+        headers: { Authorization: "Bearer " + authStore.token }
+      },
+      )
+      .then(response => {
+        return response.data
+      })
+      .catch(err => {console.log(err)})
+    },
+
+    /**
+     * Deletes an ingredient(item with amount) from the logged in account's shopping list
+     * @param ingredientId the id of the ingredient that will be removed
+     */
+    deleteItemFromShoppingList: async (ingredientId) => {
+      const authStore = useAuthStore();
+      return axios.delete(import.meta.env.VITE_BACKEND_URL + '/shoppinglist/items/' + ingredientId,
+      {
+        headers: {Authorization: "Bearer " + authStore.token }
+      })
+      .then(response => { return response.data; })
+      .catch(err => {console.log(err)})
+    },
+
+    /**
+     * Adds a suggestion to the logged in account's shopping list
+     * @param itemId the id of the item that will be suggested
+     * @param amount the amount of the specified item that will be suggested
+     */
+    addSuggestion: async (itemId, amount) => {
+      const authStore = useAuthStore();
+      return axios.put(import.meta.env.VITE_BACKEND_URL + '/shoppinglist/suggestions/' + itemId + '/' + amount, "",
+      {
+        headers: { Authorization: "Bearer " + authStore.token }
+      })
+      .then(response => { return response.data; })
+      .catch(err => {console.log(err)})
+    },
+
 
-    //returns fridgeItem of specific id
-    getFridgeItem: async (id) =>{
+    /**
+     * Accepts a suggestion and adds it to the shopping list, removing it from the suggestions list
+     * @param id the id of the ingredient that will be added to the list
+     */
+    acceptSuggestion: async (id) => {
+      const authStore = useAuthStore();
+      return axios.put(import.meta.env.VITE_BACKEND_URL + '/shoppinglist/suggestions/accept/' + id, "",
+      {
+        headers: { Authorization: "Bearer " + authStore.token }
+      })
+      .then(response => { return response.data; })
+      .catch(err => {console.log(err)})
+    },
+
+     /**
+     * Declines a suggestion and removes it from the suggestions list
+     * @param id the id of the ingredient that will be declined
+     */
+    declineSuggestion: async (id) => {
+      const authStore = useAuthStore();
+      return axios.delete(import.meta.env.VITE_BACKEND_URL + '/shoppinglist/suggestions/' + id,
+      {
+        headers: { Authorization: "Bearer " + authStore.token }
+      })
+      .then(response => { return response.data; })
+      .catch(err => {console.log(err)})
+    },
+
+
+      // addIngredientsToFridge: async (ingredientIds) => {
+      //   const authStore = useAuthStore();
+      //   return axios.delete(`${import.meta.env.VITE_BACKEND_URL}/shoppinglist/purchased`, {
+      //     headers: { Authorization: `Bearer ${authStore.token}`},
+      //     data: { ingredientIds }
+      //   })
+      //   .then((response) => {return response.data})
+      //   .catch(err => {console.log(err)})
+
+      // },
+
+      addIngredientsToFridge: async (ingredients) => {
         const authStore = useAuthStore();
+        return axios.put(`${import.meta.env.VITE_BACKEND_URL}/shoppinglist/purchased`, ingredients, {
+          headers: { Authorization: `Bearer ${authStore.token}`}
+        })
+        .then((response) => {return response.data})
+        .catch(err => {console.log(err)})
+
+      },
 
-        axios.get(`${import.meta.env.VITE_BACKEND_URL}/fridge/${id}`, {
+    /**
+     * Get recipe based on id
+     * @param id
+     * @returns {Promise<*>}
+     */
+    getRecipe: async (id) => {
+        return axios.get(`${import.meta.env.VITE_BACKEND_URL}/recipe/${id}`)
+            .then((response) => {
+                console.log(response.data);
+                return response.data;
+            })
+            .catch((error) => {
+                throw new Error(error);
+            })
+    },
+
+
+    /**
+     * Deletes account from the
+     * @param id
+     * @param token
+     * @returns {Promise<*>}
+     */
+    deleteAccount: async (id) => {
+        const authStore = useAuthStore();
+        if (!authStore.isLoggedIn) {
+            throw new Error();
+        }
+
+        return axios.delete(`${import.meta.env.VITE_BACKEND_URL}/account/${id}`, {
             headers: { Authorization: `Bearer ${authStore.token}` },
         })
+            .then(() => {
+                authStore.logout()
+                router.push('/login')
+            })
+            .catch((error) => {
+                throw new Error(error);
+            });
+
+    },
+
+    /**
+     *
+     * @param id account id
+     * @param request password and firstname
+     * @returns {Promise<*>}
+     */
+    updateAccount: async (id, request) => {
+        const authStore = useAuthStore();
+        if (!authStore.isLoggedIn) {
+            throw new Error();
+        }
+
+        return axios.put(`${import.meta.env.VITE_BACKEND_URL}/account/${id}`,request, {
+                headers: { Authorization: `Bearer ${authStore.token}` },
+            })
             .then((response) => {
+                authStore.setAccount(response.data)
                 return response.data;
+            }).catch(() => {
+                throw new Error("Error when updating account: ");
+            });
+    },
+
+    /**
+     * Updates the profile name, restriction and profile image
+     * If error: "error.message" returns the status code
+     * @param id profile id
+     * @param request
+     * @returns {Promise<*>}
+     */
+    updateProfile: async (id, request) => {
+        const authStore = useAuthStore();
+        if (!authStore.isLoggedIn) {
+            throw new Error();
+        }
+
+        return axios.put(`${import.meta.env.VITE_BACKEND_URL}/profile/${id}`,request, {
+            headers: { Authorization: `Bearer ${authStore.token}` },
+
+        })
+            .then((response) => {
+                authStore.setProfile(response.data)
+                return response.data;
+            })
+            .catch((error) => {
+                throw new Error(error.response.status);
+            });
+
+    },
+
+    /**
+     * Deletes a profile from an account
+     * @param id
+     * @param request
+     * @returns {Promise<*>}
+     */
+    deleteProfile: async (id) => {
+        const authStore = useAuthStore();
+        if (!authStore.isLoggedIn) {
+            throw new Error();
+        }
+
+        return axios.delete(`${import.meta.env.VITE_BACKEND_URL}/profile/${id}`, {
+            headers: { Authorization: `Bearer ${authStore.token}` },
+        })
+            .then(() => {
+                router.push('/selectProfile')
             })
             .catch(() => {
-                throw new Error("Could not fetch fridge item");
+                throw new Error("Kan ikke slette profil");
             });
+
     },
+
+
+
+
+
+
+
 }
\ No newline at end of file
diff --git a/src/views/FridgeView.vue b/src/views/FridgeView.vue
index cd8088e689767f9daa549a4dcaa98a65b30c4b68..6ee345d55cce6d76d913784118d191047ede2ab7 100644
--- a/src/views/FridgeView.vue
+++ b/src/views/FridgeView.vue
@@ -1,17 +1,17 @@
-<template><h1>Kjøleskap</h1><br><br>
+<template><h1>Kjøleskap</h1>
     <main>
-        <ItemSearch v-if="searchVisible" @itemsAdded="updateFridge"></ItemSearch>
+        <ItemSearch :adds-to-fridge="true" v-if="searchVisible" @itemsAdded="updateFridge"></ItemSearch>
 
-        <div id = "fridgeMsg"><p>Melding fra kjøleskapet:</p><span>{{this.fridgeMsg}}</span></div>
+        <div id = "fridgeMsg"><p v-if="this.fridgeMsg != ''">Melding fra kjøleskapet:</p><span>{{this.fridgeMsg}}</span></div>
         <eat-fridge-item-modal @closeModal="hideModal" v-if="visible" :fridge-item="selectedItem"></eat-fridge-item-modal>
 
         <div id = "itemContainer" >
-            <FridgeItem v-for="item in fridgeItems" :actualItem = "item"  @appleBtnPressed="showModal"></FridgeItem>
+            <FridgeItem v-for="item in fridgeItems" :fridgeItem = "item"  @appleBtnPressed="showModal"></FridgeItem>
         </div>
 
         <div id="addItemBtn-container">
-          <button @click="showItemSearch" id="addItemBtn">
-            <span class="plus">+</span>
+          <button :class="{ rotate: this.searchVisible }" @click="showItemSearch" class="add-button">
+            <span class="plus-sign"></span>
           </button>
         </div>
     </main>
@@ -31,14 +31,13 @@ export default {
     name: "FridgeView",
     components: {ItemSearch, EatFridgeItemModal, FridgeItem},
     computed:{
-      ...mapState(useAuthStore, ['account']),
-      ...mapStores(useFridgeStore),
+      ...mapState(useAuthStore, ['account', 'fridgeItems']),
     },
   data() {
       return {
           visible: false, //is the useitemModal visible
           selectedItem: null,
-          fridgeItems: [],
+          //fridgeItems: [],
           searchVisible: false,
           fridgeMsg: ""
       }
@@ -62,17 +61,15 @@ export default {
           this.fridgeMsg=msg;
       },
       async updateFridge(addedItem) {
-          this.fridgeItems = await API.getFridgeItems();
-          this.fridgeItems = await API.getFridgeItems();
           this.hideItemSearch();
           this.updateFridgeMessage(addedItem.name + " ble lagt i kjøleskapet.")
       },
 
   },
   async mounted() {
-      this.fridgeItems = await API.getFridgeItems();
+      await API.getFridgeItems()
       if(this.fridgeItems.length===0){
-          this.fridgeMsg="Kjøleskapet ditt er tomt. Legg inn varer ved å trykke på pluss-knappen nederst i høyre hjørne"
+          this.fridgeMsg="Kjøleskapet ditt er tomt."
       }
   }
 }
@@ -82,21 +79,24 @@ export default {
 main {
 
     color:black;
-    background-color: base.$grey;
-    padding: 2em;
+    //background-color: base.$grey;
+    padding: 1em 1em;
     min-height: 600px;
 }
 
 h1 {
   width:100%;
-  padding-left: 1em;
+  padding-left: 0.5em;
   padding-top: 2em;
-  font-weight: bold;
 }
 
 #itemContainer {
-    background-color: base.$grey;
-    padding-bottom: 5em;
+    padding-bottom: 170px;
+
+}
+
+.rotate {
+    -webkit-transform: rotate(45deg);
 }
 
 #addItemBtn {
@@ -118,16 +118,16 @@ h1 {
 }
 
 #addItemBtn-container {
-  padding-bottom: 3em;
-  z-index: 9999;
   position: fixed;
-  bottom: 15px;
-  right: 1em;
+  bottom: 75px;
+  right: 10px;
+  float: right;
 }
 
 #fridgeMsg {
   background-color: base.$light-green;
   padding: 1em;
+  min-height: 3em;
 }
 
 #fridgeMsg span, #fridgeMsg p{
@@ -135,4 +135,8 @@ h1 {
   font-weight: bolder;
   font-size: 1.2em;
 }
+
+p, span {
+  color: white;
+}
 </style>
\ No newline at end of file
diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue
index 0f9f671c983e1870a64046c51cca21bd25d04cd7..3cf09945743a39413906a51730ebe43d5644685b 100644
--- a/src/views/HomeView.vue
+++ b/src/views/HomeView.vue
@@ -1,6 +1,7 @@
 <script>
   import { useAuthStore } from "@/stores/authStore.js";
   import { mapState } from 'pinia'
+  import router from "@/router";
   import GroceryOffers from "@/components/GroceryOffers.vue";
 
   export default {
@@ -13,8 +14,6 @@
     computed: {
       ...mapState(useAuthStore, ['profile'])
     }
-
-
   }
 </script>
 
@@ -31,12 +30,15 @@
         </div>
 
         <div class="tips">
-          <img id="tips-img" src="../components/icons/logo.png" alt="Logo">
-          <p id="tips-text">Her kommer tips du kanskje kan ha nytte av, trykk på meg for å gå til neste tips!</p>
+          <img id="tips-img" src="../components/icons/tips.png" alt="Logo">
+          <p id="tips-text">Frys ned rester, så kan du ta opp en porsjon senere når du trenger et raskt måltid, i stedet for å kaste restene.</p>
         </div>
 
+        <div class="grocery">
           <grocery-offers></grocery-offers>
 
+        </div>
+
 
       </div>
   </main>
@@ -68,8 +70,8 @@
 }
 
 #tips-img {
-  width: 40px;
-  height: 40px;
+  width: 55px;
+  height: 55px;
   margin: auto 0;
 }
 
@@ -82,6 +84,7 @@
   background-color: rgb(232, 232, 232);
   margin-left: 10px;
   margin-right: 10px;
+  margin-bottom: 1.5em;
 
 
 }
diff --git a/src/views/LoginView.vue b/src/views/LoginView.vue
index fe18b47e8ece9dd949df35e5b0517c8c9c22c3a5..2a0b5b48cf99b00c92a1956c4965c477c7c1c63b 100644
--- a/src/views/LoginView.vue
+++ b/src/views/LoginView.vue
@@ -13,7 +13,6 @@
     },
     methods: {
       login() {
-        //todo: implement when API is up
         API.login({email: this.email, password: this.password}).then(() => {
                     router.push("/selectProfile");
                 })
@@ -76,6 +75,12 @@ form {
   flex-direction: column;
 }
 
+#error-message {
+  text-align: center;
+  width: 80%;
+
+}
+
 input {
   height: 40px;
   font-size: 16px;
diff --git a/src/views/MissingPage.vue b/src/views/MissingPage.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e110350375e236a41a035386fb3a907cdccc37e9
--- /dev/null
+++ b/src/views/MissingPage.vue
@@ -0,0 +1,15 @@
+<template>
+    <h1 id="msg">404</h1>
+    <h2>Oida, denne siden finnes ikke</h2>
+    <RouterLink to="/">Gå tilbake til forsiden</RouterLink>
+</template>
+
+<script>
+export default {
+    name: "MissingPage"
+}
+</script>
+
+<style scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/views/PinCodeView.vue b/src/views/PinCodeView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..3fc4116508005935b5be9317ead74fd0d38d32bd
--- /dev/null
+++ b/src/views/PinCodeView.vue
@@ -0,0 +1,54 @@
+<script>
+import router from '@/router/index.js';
+
+export default {
+    methods: {
+        sendToHomePage() {
+            router.push("/");
+        }
+    }
+}
+</script>
+
+<template>
+    <main>
+        <h1>PIN</h1>
+        <div class="pincode-container">
+            <input id="pincode-field" type="tel" maxlength="4" placeholder="0000"/>
+            <button id="pincode-button" type="button" @click="sendToHomePage">OK</button>
+        </div>
+    </main>
+</template>
+
+<style scoped lang="scss">
+h1 {
+    font-size: 50px;
+}
+main {
+    padding: 50px 10px;
+    text-align: center;
+}
+
+.pincode-container {
+    width: 100%;
+    display: flex;
+    justify-content: center;
+    padding: 10px;
+    input {
+        border-radius: 0;
+        border: 1px solid black;
+        height: 50px;
+        width: 100px;
+        margin: 0 5px;
+        font-size: 38px;
+        padding: 5px;
+    }
+}
+
+
+button {
+    border-radius: 0;
+    border: 1px solid black;
+    width: 50px;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/ProfileCreationView.vue b/src/views/ProfileCreationView.vue
index 3ea4cf01d147be6dbccb64ec9834e4aa2f47af1a..315c9cb5479a8a4d01e7a8820ab6bd6d988fe4fe 100644
--- a/src/views/ProfileCreationView.vue
+++ b/src/views/ProfileCreationView.vue
@@ -54,7 +54,7 @@ export default {
     <main>
         <h1>Ny profil</h1>
 
-        <form action="todo" method="post">
+        <form @submit.prevent="submit">
             <label for="profile_img" id="profile_img_label">
                 <div class="img_hover">
                     <img :src="image" alt="fjes" id="profile_img_preview">
diff --git a/src/views/RecipeView.vue b/src/views/RecipeView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..88fd6572f4de41dae6c0a44719f0a0255f2b3dc1
--- /dev/null
+++ b/src/views/RecipeView.vue
@@ -0,0 +1,86 @@
+<script>
+
+import {API} from "@/util/API";
+
+export default {
+    name: "RecipeView",
+    data() {
+        return {
+            recipe: {},
+            id: this.$route.params.id,
+            title: "",
+            description: "",
+            time: "",
+            ingredients: [],
+            instructions: "",
+        }
+    },
+    methods: {
+        async loadData() {
+            await API.getRecipe(this.id)
+                .then((recipe) => {
+                  this.title = recipe.title;
+                  this.description = recipe.description;
+                  this.time = recipe.time;
+                  this.ingredients = recipe.ingredient;
+                  this.instructions = recipe.instructions;
+                })
+        },
+        addIngredientsShoppingList() {
+            //TODO add ingredients to shopping list
+        },
+        removeIngredientsFromFridge() {
+            //TODO remove used ingredients from fridge
+        }
+    },
+    async mounted() {
+        await this.loadData();
+    }
+}
+
+</script>
+
+<template>
+  <main>
+      <h1>{{this.title}}</h1><br>
+      <p>{{this.description}}</p><br>
+      <div class="ingredients">
+          <h2>Ingredienser</h2>
+          <ul>
+              <li v-for="ingredient in this.ingredients">{{ ingredient.item.name }} {{ ingredient.amount.quantity }} {{ingredient.amount.unit}}</li>
+          </ul>
+          <button @click="addIngredientsShoppingList">Legg til ingrediensene i handlekurven</button>
+      </div>
+      <div class="instructions">
+          <h2>Instruksjoner</h2>
+          {{this.instructions}}
+      </div>
+      <button @click="removeIngredientsFromFridge">Fjern varene fra kjøleskapet</button>
+
+  </main>
+
+</template>
+
+<style scoped lang="scss">
+@media(min-width: base.$desktop-min) {
+  main {
+    padding-top: 45px !important;
+  }
+}
+
+main {
+  padding: 20px 10px;
+  .ingredients {
+    margin-bottom: 20px;
+  }
+    button {
+        min-height: 40px;
+        border-radius: 0;
+        border: 1px solid;
+        cursor: pointer;
+        padding: 5px;
+    }
+}
+
+
+</style>
\ No newline at end of file
diff --git a/src/views/SelectProfileView.vue b/src/views/SelectProfileView.vue
index 8b7130a3a16826fec45442d429cb7458b1a3c7f6..8dd7991f2720672dfb0ca46f75a8cb1bdd0fab1b 100644
--- a/src/views/SelectProfileView.vue
+++ b/src/views/SelectProfileView.vue
@@ -2,6 +2,7 @@
     import { API } from '@/util/API.js';
     import { useAuthStore } from "@/stores/authStore.js";
     import { mapState } from 'pinia'
+    import router from '../router';
 
     export default {
         data() {
@@ -12,7 +13,7 @@
 
         computed: {
             ...mapState(useAuthStore, ['profiles'])
-        }, 
+        },
 
         methods: {
             // Sends the user into the home page logged in as the profile they clicked on
@@ -22,7 +23,7 @@
             
             // Sends the user into the "register profile" view 
             addProfile() {
-                API.addProfile();
+                router.push('/newProfile')
             },
 
             // Receives all profiles from this user
@@ -55,7 +56,7 @@
         </div>
 
         <div class="add">
-            <button @click="addProfile">+</button>
+            <button class="add-button" @click="addProfile"><span class="plus-sign"></span></button>
         </div>
     </div>
 </template>
@@ -104,19 +105,6 @@
         padding: 10px;
     }
 
- 
-    button {
-        border-radius: 50%;
-        border-style: none;
-        width: 50px;
-        height: 50px;
-        font-size: 50px;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        padding-bottom: 10px;
-    }
-
     #selectProfileBtn {
         background-color: transparent;
         border:none;
diff --git a/src/views/SettingsView.vue b/src/views/SettingsView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..8e5e024b1585d6d88f8cd29a97dfb6454e783885
--- /dev/null
+++ b/src/views/SettingsView.vue
@@ -0,0 +1,138 @@
+<template>
+    <main>
+    <EditProfile></EditProfile>
+        <EditAccount></EditAccount>
+        <div id = "attribution ">
+            <h3>Om ikonene brukt i denne appen</h3>
+            <a href="https://www.flaticon.com/free-icons/leaf" title="leaf icons">Leaf icons created by Freepik - Flaticon</a>
+            <p>Icons by <a href="https://iconify.design/">Iconify</a></p>
+        </div>
+    </main>
+</template>
+<script setup>
+
+import EditProfile from "../components/EditProfile.vue";
+import EditAccount from "../components/EditAccount.vue";
+</script>
+
+
+<script>
+import {mapStores} from "pinia";
+import {Icon} from "@iconify/vue";
+import {API} from "@/util/API";
+import { useAuthStore } from "@/stores/authStore";
+import router from "../router";
+export default {
+    name: "ProfileSettings",
+    components: {Icon},
+    computed: {
+        ...mapStores(useAuthStore),
+        iconColor() {
+            return "#000000"
+        },
+    },
+    beforeMount() {
+        if (!useAuthStore().isLoggedIn) {
+            router.push('/login')
+        }
+    },
+}
+</script>
+
+<style scoped lang ="scss">
+
+
+main {
+  background-color: white;
+  color:black;
+  display:flex;
+  justify-content: center;
+  align-items: center;
+  flex-direction: column;
+  width: 100%;
+  text-align: left;
+  left:0;
+}
+
+#profilepicture-container {
+    display:flex;
+    border-radius:50%;
+    width:100px;
+    height: 100px;
+    background-color: white;
+    justify-content: center;
+    align-items: center;
+    border: 3px solid base.$grey;
+}
+
+img {
+  border-radius: 50%;
+}
+
+#changeUserImage {
+    display:flex;
+}
+
+#changeUserImage #profilepicture-container {
+  width: 50px;
+  height: 50px;
+}
+
+.infoText {
+  background-color: white;
+  padding: .5em;
+  margin: .4em;
+}
+
+form {
+    background-color: base.$grey;
+    color: black;
+    align-content: end;
+    padding: 2em;
+    margin-top: 2em;
+    margin-bottom: 2em;
+}
+
+input[type="text"],
+input[type="password"]{
+    width: 100%;
+    padding: .5em;
+}
+#submitbuttonBox {
+    display:flex;
+    justify-content: space-between;
+}
+button {
+    background-color: base.$red;
+    color: black;
+
+    border: 1px solid black;
+
+    margin: 1em;
+}
+
+
+#changeUserBtn {
+    padding:.9em;
+
+}
+button:hover{
+   background-color: #282828;
+
+ }
+
+.saveBtn, .delBtn {
+  background-color: base.$green;
+  color: white;
+  font-weight: bold;
+  padding:.9em;
+  border:none;
+}
+.delBtn {
+  background-color: darkred;
+}
+
+#dangerZone {
+  color: darkred;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/ShoppingListView.vue b/src/views/ShoppingListView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7501e1ad2c5feab9e15f678a8c07acfacbe99a87
--- /dev/null
+++ b/src/views/ShoppingListView.vue
@@ -0,0 +1,372 @@
+<template>
+    <div class="container">
+        <h1 v-if="this.items.suggestionList.length === 0">Handleliste</h1>
+
+        <ItemSearch v-if="this.showAddMenu && this.profile.restricted"
+            @itemsAdded="(ingredient) => updateSuggestionList(ingredient)" :addsToFridge="false"></ItemSearch>
+        <ItemSearch v-else-if="this.showAddMenu && !this.profile.restricted"
+            @itemsAdded="(ingredient) => updateShoppingList(ingredient)" :addsToFridge="false"></ItemSearch>
+
+        <div class="list">
+            <div class="items">
+
+                <div v-if="items.suggestionList.length > 0" class="suggestions-wrapper">
+                    <h2>Forslag</h2>
+                    <div v-for="(item, index) in items.suggestionList" :key="index" :item="item" class="item">
+
+                        <div class="item-wrapper">
+                            <div class="item-label">
+                                <label v-if="item.amount.quantity === 1" for="checkbox" class="checkbox-label">{{
+                                    item.item.name }}</label>
+                                <label v-else for="checkbox" class="checkbox-label">{{ item.amount.quantity }}x {{
+                                    item.item.name }}</label>
+                            </div>
+                        </div>
+
+                        <div class="buttons">
+                            <button v-if="!this.profile.restricted" class="accept-button"
+                                @click="acceptItem(item.ingredient_id)">Godta</button>
+                            <button class="decline-button" @click="declineItem(item.ingredient_id)">Avslå</button>
+                        </div>
+
+                    </div>
+                </div>
+
+
+                <h2 v-if="this.items.ingredientList.length > 0 && this.items.suggestionList > 0">Handleliste</h2>
+                <div v-for="(item, index) in items.ingredientList" :key="index" :item="item" class="item">
+
+                    <div class="item-wrapper">
+                        <div class="check">
+                            <input v-model="item.isChecked" @change="sortList" class="checkbox" type="checkbox">
+                        </div>
+
+                        <div class="item-label">
+                            <label v-if="item.amount.quantity === 1" for="checkbox" class="checkbox-label">{{ item.item.name
+                            }}</label>
+                            <label v-else for="checkbox" class="checkbox-label">{{ item.amount.quantity }}x {{
+                                item.item.name }}</label>
+                        </div>
+                    </div>
+
+                    <div class="buttons">
+                        <img id="delete-button" @click="deleteItem(item.ingredient_id)" src="../components/icons/trash.svg" alt="delete">
+                    </div>
+
+                </div>
+            </div>
+
+        </div>
+        <div class="add">
+            <button :class="{ rotate: this.showAddMenu }" class="add-button" @click="addItem"><span class="plus-sign"></span></button>
+        </div>
+    </div>
+</template>
+
+<script>
+import { API } from '../util/API.js';
+import { mapState } from 'pinia';
+import { useAuthStore } from "@/stores/authStore.js";
+import ItemSearch from '../components/ItemSearch.vue'
+
+
+export default {
+    data() {
+        return {
+            testItems: [{ itemName: "banan", amount: 2, isChecked: false }, { itemName: "ost", amount: 1, isChecked: false }, { itemName: "eple", amount: 4, isChecked: false }, { itemName: "brus", amount: 1, isChecked: false }],
+            ingredients: [],
+            showAddMenu: false,
+        }
+    },
+    components: {
+        ItemSearch
+    },
+    methods: {
+        sortList() {
+            this.items.ingredientList.sort((a, b) => a.isChecked - b.isChecked)
+        },
+        async getShoppingList() {
+            await API.getShoppingList()
+                .catch(err => { console.log(err) })
+        },
+        async addItem() {
+            this.showAddMenu = !this.showAddMenu;
+            window.scrollTo({ top: 0, behavior: 'smooth' });
+
+        },
+        async acceptItem(id) {
+            await API.acceptSuggestion(id)
+                .then((response) => {
+                    this.items.suggestionList.forEach((ingredient, index) => {
+                        if (ingredient.ingredient_id === response.ingredient_id) {
+                            this.items.suggestionList.splice(index, 1);
+                        }
+                    })
+                    this.updateShoppingList(response)
+                })
+
+        },
+        async declineItem(id) {
+            await API.declineSuggestion(id)
+                .then((response) => {
+                    this.items.suggestionList.forEach((ingredient, index) => {
+                        if (ingredient.ingredient_id === response.ingredient_id) {
+                            this.items.suggestionList.splice(index, 1);
+                        }
+                    })
+                })
+        },
+        async deleteItem(id) {
+            await API.deleteItemFromShoppingList(id)
+                .then(() => {
+                    this.items.ingredientList.forEach((ingredient, index) => {
+                        if (ingredient.ingredient_id === id) {
+                            this.items.ingredientList.splice(index, 1);
+                        }
+                    })
+                })
+
+        },
+        addIsCheckedToIngredient() {
+            this.items.ingredientList.forEach(ingredient => {
+                if (!ingredient.hasOwnProperty('isChecked')) {
+                    ingredient.isChecked = false;
+                }
+            })
+        },
+        updateShoppingList(ingredient) {
+            ingredient.isChecked = false;
+            this.items.ingredientList.push(ingredient);
+            this.showAddMenu = false;
+        },
+        updateSuggestionList(ingredient) {
+            ingredient.isChecked = false;
+            this.items.suggestionList.push(ingredient)
+            this.showAddMenu = false;
+        },
+        sendIngredientsToFridge() {
+            const boughtIngredients = []
+
+            this.items.ingredientList.forEach(ingredient => {
+                if (ingredient.isChecked) {
+                    boughtIngredients.push(ingredient)
+                }
+            })
+            console.log(boughtIngredients)
+            API.addIngredientsToFridge(boughtIngredients)
+        }
+
+    },
+    computed: {
+        ...mapState(useAuthStore, ['items', 'profile'])
+    },
+    async mounted() {
+        await this.getShoppingList()
+            .then(() => {
+                this.items.ingredientList.forEach(item => {
+                    item.isChecked = false
+                })
+            })
+    },
+    beforeRouteLeave (to, from) {
+        this.sendIngredientsToFridge()
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    margin: auto;
+
+    max-width: 550px;
+    margin-top: 4em;
+    height: 100%;
+}
+
+h1 {
+
+  width:100%;
+  padding-left: 0.5em;
+
+}
+
+
+
+.rotate {
+    -webkit-transform: rotate(45deg);
+}
+
+.accept-button {
+    border-radius: 10px;
+    background-color: base.$light-green;
+    color: white;
+    font-weight: bold;
+    border-style: none;
+    height: 27px;
+    padding: 0 10px;
+}
+
+.decline-button {
+    border-radius: 10px;
+    background-color: base.$grey;
+    color: base.$indigo;
+    font-weight: bold;
+    border-style: none;
+    height: 27px;
+    padding: 0 10px;
+    margin: 0 auto;
+
+}
+
+.buttons {
+    display: flex;
+    gap: 5px;
+    align-self: center
+}
+
+
+h2 {
+    padding: 5px 15px
+}
+
+
+
+.add {
+    position: fixed;
+    bottom: 75px;
+    right: 10px;
+    float: right;
+}
+
+.header {
+    display: flex;
+    align-items: left;
+    justify-content: left;
+    padding-left: 15px;
+    width: 100%;
+    border-bottom: 1px solid base.$grey;
+}
+
+.list {
+    min-width: 300px;
+    min-height: 100vh;
+    height: 100%;
+    /* background-color: #F3F4F9; */
+    width: 100%;
+    // padding: 15px;
+    // border-radius: 10px;
+}
+
+.items {
+    padding-bottom: 170px;
+}
+
+.suggestions-wrapper {
+    border-bottom: 1px solid base.$grey;
+    border-width: 100%;
+    padding-bottom: 15px;
+
+
+}
+
+.item {
+    display: flex;
+    flex-direction: row;
+    gap: 10px;
+    justify-content: space-between;
+    background-color: white;
+    padding: 5px 15px;
+    padding: 0.5em 1em;
+    border-top-right-radius: 10px;
+    border-top-left-radius: 10px;
+
+}
+
+.item:not(:first-child) {
+    border-radius: 0px;
+}
+
+.item:last-child {
+    border-radius: 0px;
+    border-bottom-left-radius: 10px;
+    border-bottom-right-radius: 10px;
+}
+
+// .item:not(:last-child)::after {
+//     content: '';
+//     /* this works like a border-width */
+//     height: 1px;
+//     /* percentage of border shown */
+//     width: 70%;
+//     /* the color of border */
+//     background: base.$grey; 
+//     position: absolute;
+//     bottom: 0;
+//     margin: 0 auto;
+//     left: 0;
+//     /* horizontal centering */
+//     right: 0;
+// }
+
+.item-wrapper {
+    display: flex;
+    flex-direction: row;
+    gap: 10px;
+
+}
+
+input[type="checkbox"] {
+    -webkit-appearance: none;
+    -moz-appearance: none;
+    appearance: none;
+    width: 35px;
+    height: 35px;
+    border-radius: 50%;
+    border: 2px solid #ccc;
+
+}
+
+input[type="checkbox"]:checked {
+    background-color: base.$light-green;
+}
+
+input[type="checkbox"]:checked:after {
+    content: "\2713";
+    /* Unicode code for checkmark symbol */
+    font-size: 24px;
+    font-weight: bold;
+    color: white;
+    text-align: center;
+    line-height: 35px;
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%, -50%);
+}
+
+label {
+    font-size: 20px;
+}
+
+img {
+    width: 30px;
+    height: 30px;
+    padding: 5px;
+
+    max-height: 100%;
+    max-width: 100%;
+}
+
+.check {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.delete {
+    align-self: flex-end;
+}</style>
\ No newline at end of file
diff --git a/src/views/__tests__/FridgeView.spec.js b/src/views/__tests__/FridgeView.spec.js
index 4790f4ad2639935f3da4a5694dafcb3a27738181..4312e6a5f91ac7d53812647c27bb300461c284b0 100644
--- a/src/views/__tests__/FridgeView.spec.js
+++ b/src/views/__tests__/FridgeView.spec.js
@@ -38,7 +38,7 @@ describe('Fridge', () => {
 
         })
         expect(wrapper.find('ItemSearch').exists()).toBe(false);
-        await wrapper.find('#addItemBtn').trigger('click');
+        await wrapper.find('.add-button').trigger('click');
 
         setTimeout(() => {
             expect(wrapper.find('ItemSearch').exists()).toBe(true);
diff --git a/src/views/__tests__/SelectProfileView.spec.js b/src/views/__tests__/SelectProfileView.spec.js
index 858b394a2c36720176fd2f1cf9e157e4b6673907..c0b9d55f0f528f4c4f3d4cbe65a125804b500fad 100644
--- a/src/views/__tests__/SelectProfileView.spec.js
+++ b/src/views/__tests__/SelectProfileView.spec.js
@@ -13,7 +13,6 @@ describe('Select profile', () => {
       },
     })
     expect(wrapper.text()).toContain('Hvem bruker appen?')
-    expect(wrapper.text()).toContain('+')
   })
 
   it('loads with one profile', () => {
diff --git a/src/views/__tests__/ShoppingListView.spec.js b/src/views/__tests__/ShoppingListView.spec.js
new file mode 100644
index 0000000000000000000000000000000000000000..97988ad4314e26355b1a35af1ea4c27b25874b62
--- /dev/null
+++ b/src/views/__tests__/ShoppingListView.spec.js
@@ -0,0 +1,211 @@
+import { describe, it, expect, vi} from 'vitest'
+import { mount } from '@vue/test-utils'
+import { createTestingPinia } from '@pinia/testing'
+import ShoppingListView from '../ShoppingListView.vue'
+
+
+  
+  describe('Shopping list', () => {
+    const wrapper = mount(ShoppingListView, 
+        { computed: {
+            items() {
+                return {
+                    id: 1,
+                    ingredientList: [
+                    {
+                        ingredient_id: 1,
+                        amount: {
+                        quantity: 1,
+                        unit: "stk"
+                        },
+                        item: {
+                        id: 1,
+                        name: "Vegansk Krone-Is Jordbær",
+                        ean: "7041012550001",
+                        shelfLife: 30,
+                        image_url: "https://bilder.ngdata.no/7041012550001/meny/large.jpg",
+                        amount: {
+                            quantity: 4,
+                            unit: "stk"
+                        },
+                        store: null,
+                        allergens: [
+                            {
+                            name: "Nøtter (kan inneholde spor)"
+                            },
+                            {
+                            name: "Peanøtter (kan inneholde spor)"
+                            },
+                            {
+                            name: "Soya (kan inneholde spor)"
+                            }
+                        ],
+                        nutrition: [
+                            {
+                            name: "Kalorier",
+                            amount: {
+                                quantity: 264,
+                                unit: "stk"
+                            }
+                            },
+                            {
+                            name: "Energi",
+                            amount: {
+                                quantity: 1106,
+                                unit: "stk"
+                            }
+                            },
+                            {
+                            name: "Fett",
+                            amount: {
+                                quantity: 11.2,
+                                unit: "g"
+                            }
+                            },
+                            {
+                            name: "Karbohydrater",
+                            amount: {
+                                quantity: 38.7,
+                                unit: "g"
+                            }
+                            },
+                            {
+                            name: "Mettet fett",
+                            amount: {
+                                quantity: 9.5,
+                                unit: "g"
+                            }
+                            },
+                            {
+                            name: "Protein",
+                            amount: {
+                                quantity: 1.5,
+                                unit: "g"
+                            }
+                            },
+                            {
+                            name: "Salt",
+                            amount: {
+                                quantity: 0.11,
+                                unit: "g"
+                            }
+                            },
+                            {
+                            name: "Sukkerarter",
+                            amount: {
+                                quantity: 23.6,
+                                unit: "g"
+                            }
+                            }
+                        ]
+                        },
+                        exp_date: null
+                    },
+                    {
+                        ingredient_id: 2,
+                        amount: {
+                        quantity: 1,
+                        unit: "stk"
+                        },
+                        item: {
+                        id: 2,
+                        name: "Jarlsberg Gulost",
+                        ean: "7038010053368",
+                        shelfLife: 14,
+                        image_url: "https://bilder.ngdata.no/7038010053368/kmh/large.jpg",
+                        amount: {
+                            quantity: 700,
+                            unit: "g"
+                        },
+                        store: null,
+                        allergens: [
+                            {
+                            name: "Melk"
+                            }
+                        ],
+                        nutrition: [
+                            {
+                            name: "Kalorier",
+                            amount: {
+                                quantity: 351,
+                                unit: "kcal"
+                            }
+                            },
+                            {
+                            name: "Energi",
+                            amount: {
+                                quantity: 1458,
+                                unit: "kj"
+                            }
+                            },
+                            {
+                            name: "Fett",
+                            amount: {
+                                quantity: 27,
+                                unit: "g"
+                            }
+                            },
+                            {
+                            name: "Karbohydrater",
+                            amount: {
+                                quantity: 0,
+                                unit: "g"
+                            }
+                            },
+                            {
+                            name: "Mettet fett",
+                            amount: {
+                                quantity: 17,
+                                unit: "g"
+                            }
+                            },
+                            {
+                            name: "Protein",
+                            amount: {
+                                quantity: 27,
+                                unit: "g"
+                            }
+                            },
+                            {
+                            name: "Salt",
+                            amount: {
+                                quantity: 1.1,
+                                unit: "g"
+                            }
+                            },
+                            {
+                            name: "Sukkerarter",
+                            amount: {
+                                quantity: 0,
+                                unit: "g"
+                            }
+                            }
+                        ]
+                        },
+                        exp_date: null
+                    }
+                    ],
+                    suggestionList: []
+                }    
+            }
+            },
+            global: {
+                plugins: [createTestingPinia({
+                    createSpy: vi.fn,
+                })],
+                },
+        
+        })
+
+  it('renders properly', () => {
+
+    expect(wrapper.text()).toContain('Handleliste')
+    expect(wrapper.text()).not.toContain('Forslag')
+  })
+
+  it('items gets shown', () => {
+    expect(wrapper.text()).toContain('Vegansk Krone-Is Jordbær')
+    expect(wrapper.text()).toContain('Jarlsberg Gulost')
+  })
+
+})