diff --git a/package-lock.json b/package-lock.json
index 325009f43a1e9ac5e917359abdc88e3764ea8973..0e41c4d52d0928c850db5bcb9ea7a342a14d6a2b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,7 @@
         "@iconify/vue": "^4.1.1",
         "@pinia/testing": "^0.0.16",
         "jwt-decode": "^3.1.2",
+        "lodash": "^4.17.21",
         "pinia": "^2.0.35",
         "pinia-plugin-persistedstate": "^3.1.0",
         "vue": "^3.2.45",
@@ -3836,8 +3837,7 @@
     "node_modules/lodash": {
       "version": "4.17.21",
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
-      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
-      "dev": true
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
     },
     "node_modules/lodash.once": {
       "version": "4.1.1",
diff --git a/package.json b/package.json
index 0eb0aa1f4754b48a7823428f190f1a111aca44af..7a96571b84bc49ee76db855c7ade3f24b03d71ca 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,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/FridgeItem.vue b/src/components/FridgeItem.vue
index d259d5db29f607aa03b9464483dd6c51132e4164..1d58f426274b49c89a218ce4b94c9431aab99ba4 100644
--- a/src/components/FridgeItem.vue
+++ b/src/components/FridgeItem.vue
@@ -10,7 +10,6 @@
     </div>
 
 </div>
-    <hr>
 </template>
 
 <script>
@@ -112,13 +111,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..12298cc97c69a64911f856fa1887a3864ca006ca 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:'',
@@ -56,6 +64,22 @@ 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"))
+        },
+        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 +98,14 @@ select {
 
 }
 
+#items-input {
+    margin-bottom: 1em;
+}
+
+#search-button {
+    margin-left: 0.5em;
+}
+
 #searchBoxDiv {
     display:flex;
     width:100%;
@@ -91,14 +123,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 788592a89408f9515e0cedc16804a5f890e546db..6e2e12e21b564f1fa9ec4ec8c75ee96072e5b47c 100644
--- a/src/components/Navbar.vue
+++ b/src/components/Navbar.vue
@@ -18,7 +18,7 @@
                     </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>
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__/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/router/index.js b/src/router/index.js
index 010ff3cc25d1fb1dd8dafae01bc7ed655878acf9..cf14f5330cb9f4cca178d0d7db316441fe80727f 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -8,6 +8,7 @@ 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),
@@ -51,7 +52,12 @@ const router = createRouter({
       path: '/recipe/:id',
       name: 'recipe',
       component: RecipeView
-    }
+    },
+    {
+      path: '/shoppingList',
+      name: 'shoppingList',
+      component: ShoppingListView
+    },
   ]
 })
 
diff --git a/src/stores/authStore.js b/src/stores/authStore.js
index 70f611f62d6072269cf375c59fd42826cc0c2ca0..1aaf2007015cfaf17202ac2026888ecadfe05e96 100644
--- a/src/stores/authStore.js
+++ b/src/stores/authStore.js
@@ -5,7 +5,8 @@ export const useAuthStore = defineStore("auth", {
       token: "",
       account: {},
       profile: {},
-      profiles: []
+      profiles: [],
+      items: {ingredientList: [], suggestionList: []}
     };
   },
   persist: {
@@ -31,6 +32,12 @@ export const useAuthStore = defineStore("auth", {
     },
     setProfiles(profiles) {
       this.profiles = profiles;
+    },
+    setItems(items) {
+      this.items = items;
+    },
+    setItem(item) {
+      this.items.push(item);
     }
   }
 });
diff --git a/src/style.scss b/src/style.scss
index c7158435ec70a7af663f63d364e5946679272560..9a2b66fdb2767791e8529c854f69a6df196f92ea 100644
--- a/src/style.scss
+++ b/src/style.scss
@@ -3,13 +3,45 @@ $green: #00663C;
 $light-green: hsla(160, 100%, 37%, 1);
 $white:#FFFFFF;
 $grey:#D9D9D9;
+$light-grey: #F3F4F9;
 $red:#EE6D6D;
 
 $red-hover: darken( $red, 5% );
 $green-hover: darken( $green, 8% );
 $light-green-hover: darken( $light-green, 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%;
+}
\ No newline at end of file
diff --git a/src/util/API.js b/src/util/API.js
index 97cde9c4e9c91048b5be41b0b7d448cf5395b118..db0615097ee0bac3af900ac26c3114e21f3d5e4a 100644
--- a/src/util/API.js
+++ b/src/util/API.js
@@ -64,7 +64,11 @@ 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}`, {
@@ -134,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 },
@@ -152,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})
@@ -264,6 +272,138 @@ 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)})
+    },
+
+
+    /**
+     * 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)})
+    },
+
+     /**
+     * Searches for registered items.
+     * @param searchPhrase  Name of the item that one is looking for (e.g: "purre")
+     * @returns {Promise<*>} list containing items that match the search phrase
+     */
+      searchItems: async(searchPhrase)=> {
+        return axios.get(`${import.meta.env.VITE_BACKEND_URL}/item/search?name=${searchPhrase}`, {
+        }).then((response) => {
+            return response.data.content;
+        }).catch(()=> {
+            throw new Error("Error when searching for item ");
+        })
+      },
+
+      // 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)})
+
+      },
+
+  
+
     /**
      * Get recipe based on id
      * @param id
diff --git a/src/views/FridgeView.vue b/src/views/FridgeView.vue
index cd8088e689767f9daa549a4dcaa98a65b30c4b68..a52a9ddb21d8bb8156bbf32b788e9e9785c165d9 100644
--- a/src/views/FridgeView.vue
+++ b/src/views/FridgeView.vue
@@ -1,8 +1,8 @@
-<template><h1>Kjøleskap</h1><br><br>
+<template><h1>Kjøleskap</h1>
     <main>
         <ItemSearch 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" >
@@ -10,8 +10,8 @@
         </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>
@@ -72,7 +72,7 @@ export default {
   async mounted() {
       this.fridgeItems = 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 +82,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 +121,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 +138,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..af7052980cac33be13f5f373d144934daaa8f204 100644
--- a/src/views/HomeView.vue
+++ b/src/views/HomeView.vue
@@ -31,12 +31,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 +71,8 @@
 }
 
 #tips-img {
-  width: 40px;
-  height: 40px;
+  width: 55px;
+  height: 55px;
   margin: auto 0;
 }
 
@@ -82,6 +85,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..17694f15d73d1c73d27affc3f75fcc27bfa6a233 100644
--- a/src/views/LoginView.vue
+++ b/src/views/LoginView.vue
@@ -76,6 +76,12 @@ form {
   flex-direction: column;
 }
 
+#error-message {
+  text-align: center;
+  width: 80%;
+
+}
+
 input {
   height: 40px;
   font-size: 16px;
diff --git a/src/views/ProfileCreationView.vue b/src/views/ProfileCreationView.vue
index 1f0d2c8e3c0076dd8e98c873b0f3c60aa1ea04f0..560f3c5d29264e61c614ce618b6cf56f8e162220 100644
--- a/src/views/ProfileCreationView.vue
+++ b/src/views/ProfileCreationView.vue
@@ -50,7 +50,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/SelectProfileView.vue b/src/views/SelectProfileView.vue
index 8b7130a3a16826fec45442d429cb7458b1a3c7f6..d8bd68c631b574e531cf4a7e7381c9c254d2435b 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() {
@@ -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/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')
+  })
+
+})