Skip to content
Snippets Groups Projects
UserItems.vue 10.6 KiB
Newer Older
henrikburmann's avatar
henrikburmann committed
<template>
  <!-- Shows all the items a user has posted with search and pagination.
       Includes a dropdown menu for editing or deleting an item. -->
Gilgard's avatar
Gilgard committed
  <div id="headline" class="text-xl md:text-2xl text-primary-light font-medium">
henrikburmann's avatar
henrikburmann committed
    Mine gjenstander
henrikburmann's avatar
henrikburmann committed
  </div>
  <!-- Search field -->
Titus Netland's avatar
Titus Netland committed
  <div class="relative mx-4" id="searchComponent">
Erik Borgeteien Hansen's avatar
Erik Borgeteien Hansen committed
    <span class="absolute inset-y-0 left-0 flex items-center pl-3">
      <svg class="w-5 h-5 text-gray-400" viewBox="0 0 24 24" fill="none">
        <path
          d="M21 21L15 15M17 10C17 13.866 13.866 17 10 17C6.13401 17 3 13.866 3 10C3 6.13401 6.13401 3 10 3C13.866 3 17 6.13401 17 10Z"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
        ></path>
      </svg>
    </span>
henrikburmann's avatar
henrikburmann committed

Erik Borgeteien Hansen's avatar
Erik Borgeteien Hansen committed
    <input
      type="text"
      id="searchInput"
      class="w-full py-3 pl-10 pr-4 text-gray-700 bg-white border rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-primary-medium dark:focus:border-primary-medium focus:outline-none focus:ring"
Titus Netland's avatar
Titus Netland committed
      placeholder="Søk"
Erik Borgeteien Hansen's avatar
Erik Borgeteien Hansen committed
      v-model="search"
      @change="searchWritten"
    />
  </div>
Titus Netland's avatar
Titus Netland committed
  <div class="absolute inset-x-0">
Erik Borgeteien Hansen's avatar
Erik Borgeteien Hansen committed
    <!-- ItemCards -->
    <div class="flex items-center justify-center w-screen">
      <!-- Shows items based on pagination -->
      <div
        class="grid grid-flow-row-dense grid-cols-2 md:grid-cols-4 lg:grid-cols-5 w-full"
Erik Borgeteien Hansen's avatar
Erik Borgeteien Hansen committed
        v-if="showItems"
      >
        <div
          class="cardContainer"
          id="item"
          v-for="item in visibleItems"
          :key="item"
        >
Titus Netland's avatar
Titus Netland committed
          <div class="w-full">
          <ItemCard
            id="ItemCardPage"
            class="ItemCard w-full h-full"
            :item="item"
          />
        </div>

          <!-- Dropdown menu with options for editing an item and deleting an item -->
          <TripleDotButton class="DotButton" @click="openDotMenu(item)"/>
henrikburmann's avatar
henrikburmann committed

          <div
            v-show="item.toggle"
Titus Netland's avatar
Titus Netland committed
            class="options z-10 w-44 text-base list-none bg-white rounded divide-y divide-gray-100 shadow dark:bg-gray-700 pt-4 pl-12"
henrikburmann's avatar
henrikburmann committed
          >
            <ul
              class="py-1 absolute bg-white ring-1 ring-gray-300 rounded-xl"
              aria-labelledby="dropdownDefault"
            >
              <li>
                <button
Gilgard's avatar
Gilgard committed
                  @click="
                    this.$router.push('/item/' + item.listingID + '/edit')
                  "
henrikburmann's avatar
henrikburmann committed
                  class="block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
                >
                  Rediger gjenstand
                </button>
              </li>
              <li>
                <button
                  @click="goToDeleteItem(item.listingID)"
                  class="block py-2 px-4 text-sm text-error-medium hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
                >
                  Slett gjenstand
                </button>
              </li>
            </ul>
          </div>
henrikburmann's avatar
henrikburmann committed

        <!-- A waring asking the user if it is sure it wants to delete the item
             with options to go ahead with the deleting or to cancel the delete. -->
henrikburmann's avatar
henrikburmann committed
        <CustomFooterModal
          @close="this.readyToDelete = false"
          :visible="readyToDelete"
          :title="'Sikker på at du vil slette annonsen?'"
henrikburmann's avatar
henrikburmann committed
          :message="''"
henrikburmann's avatar
henrikburmann committed
          <div class="flex justify-center p-2">
            <ColoredButton
              id="#cancelDeleteButton1"
henrikburmann's avatar
henrikburmann committed
              :text="'Avbryt'"
              @click="cancelDelete"
              class="bg-gray-500 m-2"
            ></ColoredButton>
henrikburmann's avatar
henrikburmann committed
            <ColoredButton
              id="confirmDeleteButton1"
henrikburmann's avatar
henrikburmann committed
              @click="deleteItem"
              :text="'Slett'"
              class="m-2 bg-error-medium"
            >
            </ColoredButton>
henrikburmann's avatar
henrikburmann committed
        </CustomFooterModal>
henrikburmann's avatar
henrikburmann committed
      </div>
Erik Borgeteien Hansen's avatar
Erik Borgeteien Hansen committed

      <!-- Shows items based on search field input -->
      <div
        class="grid grid-flow-row-dense grid-cols-2 md:grid-cols-4 lg:grid-cols-5 w-full place-items-center"
        v-if="showSearchedItems"
      >
        <div class="cardContainer" v-for="item in searchedItems" :key="item">
Titus Netland's avatar
Titus Netland committed
          <div class="w-full">
Titus Netland's avatar
Titus Netland committed
            <ItemCard
              id="ItemCardSearch"
              class="ItemCard w-full h-full"
              :item="item"
            />
Titus Netland's avatar
Titus Netland committed
          </div>
henrikburmann's avatar
henrikburmann committed

          <!-- Dropdown menu with options for editing an item and deleting an item -->
          <TripleDotButton class="DotButton" @click="openDotMenu(item)"/>
          <div
            v-show="item.toggle"
            class="options z-10 w-44 text-base list-none bg-white rounded divide-y divide-gray-100 shadow dark:bg-gray-700"
henrikburmann's avatar
henrikburmann committed
          >
            <ul
              class="py-1 absolute bg-white ring-1 ring-gray-300 rounded-xl"
              aria-labelledby="dropdownDefault"
            >
              <li>
                <button
Gilgard's avatar
Gilgard committed
                  @click="
                    this.$router.push('/item/' + item.listingID + '/edit')
                  "
                  class="block py-2 px-4 text-sm text-gray-700 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
                >
                  Rediger gjenstand
                </button>
              </li>
              <li>
                <button
                  @click="goToDeleteItem(item.listingID)"
                  class="block py-2 px-4 text-sm text-error-medium hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
                >
                  Slett gjenstand
                </button>
              </li>
            </ul>
          </div>
henrikburmann's avatar
henrikburmann committed
        </div>

        <!-- A waring asking the user if it is sure it wants to delete the item
             with options to go ahead with the deleting or to cancel the delete. -->
henrikburmann's avatar
henrikburmann committed
        <CustomFooterModal
          @close="this.readyToDelete = false"
          :visible="readyToDelete"
          :title="'Sikker på at du vil slette annonsen?'"
          :message="''"
        >
          <div class="flex justify-center p-2">
            <ColoredButton
              id="#cancelDeleteButton"
              :text="'Avbryt'"
              @click="cancelDelete"
              class="bg-gray-500 m-2"
            ></ColoredButton>

            <ColoredButton
              id="confirmDeleteButton"
              @click="deleteItem"
              :text="'Slett'"
              class="m-2 bg-error-medium"
            >
            </ColoredButton>
          </div>
        </CustomFooterModal>
henrikburmann's avatar
henrikburmann committed
      </div>
    </div>
Erik Borgeteien Hansen's avatar
Erik Borgeteien Hansen committed
    <!-- pagination -->
    <div class="flex justify-center" v-if="showItems">
      <PaginationTemplate
        v-bind:items="items"
        v-on:page:update="updatePage"
        v-bind:currentPage="currentPage"
        v-bind:pageSize="pageSize"
        class="mt-10"
      />
    </div>
  </div>
henrikburmann's avatar
henrikburmann committed
</template>
<script>
henrikburmann's avatar
henrikburmann committed
import TripleDotButton from "@/components/BaseComponents/TripleDotButton.vue";
henrikburmann's avatar
henrikburmann committed
import { GetUserListings, getItemPictures } from "@/utils/apiutil";
import ColoredButton from "@/components/BaseComponents/ColoredButton.vue";

import UserService from "@/services/user.service";
henrikburmann's avatar
henrikburmann committed
import ItemCard from "@/components/ItemComponents/ItemCard.vue";
import PaginationTemplate from "@/components/BaseComponents/PaginationTemplate";
import CustomFooterModal from "@/components/BaseComponents/CustomFooterModal.vue";
henrikburmann's avatar
henrikburmann committed

export default {
  name: "UserItems",
  components: {
    ItemCard,
henrikburmann's avatar
henrikburmann committed
    TripleDotButton,
Erik Borgeteien Hansen's avatar
Erik Borgeteien Hansen committed
    PaginationTemplate,
    CustomFooterModal,
    ColoredButton,
henrikburmann's avatar
henrikburmann committed
  },
  data() {
    return {
      items: [],
      item: {
        listingID: 0,
        img: "",
        address: "",
        title: "",
        pricePerDay: 0,
henrikburmann's avatar
henrikburmann committed
        toggle: false,
henrikburmann's avatar
henrikburmann committed
      },
      chosenItem: null,
henrikburmann's avatar
henrikburmann committed
      showItems: true,
      showSearchedItems: false,
Erik Borgeteien Hansen's avatar
Erik Borgeteien Hansen committed
      search: "",
henrikburmann's avatar
henrikburmann committed
      readyToDelete: false,
      dropdown: false,
henrikburmann's avatar
henrikburmann committed
      //Variables connected to pagination
      currentPage: 0,
      pageSize: 12,
      visibleItems: [],
    };
  },
  computed: {
    /**
     * Searchs items based on their title, address and price per day.
     */
henrikburmann's avatar
henrikburmann committed
    searchedItems() {
      let filteredItems = [];

      filteredItems = this.items.filter(
        (p) =>
          p.title.toLowerCase().includes(this.search.toLowerCase()) ||
          p.address.toLowerCase().includes(this.search.toLowerCase()) ||
          p.pricePerDay === Number(this.search)
      );

      return filteredItems;
    },
  },
  methods: {
    openDotMenu(item) {
      if (item.toggle == false) {
        for (var i = 0; i < this.visibleItems.length; i++) {
henrikburmann's avatar
henrikburmann committed
          this.visibleItems[i].toggle = false;
henrikburmann's avatar
henrikburmann committed
        item.toggle = true;
henrikburmann's avatar
henrikburmann committed
        item.toggle = false;
      }
    },
henrikburmann's avatar
henrikburmann committed
    getUserListingsFromAPI: async function () {
      this.items = await GetUserListings();
      for (var i = 0; i < this.items.length; i++) {
henrikburmann's avatar
henrikburmann committed
        this.items[i].toggle = false;
henrikburmann's avatar
henrikburmann committed
        let images = await getItemPictures(this.items[i].listingID);
        if (images.length > 0) {
          this.items[i].img = images[0].picture;
        }
      }
    },
henrikburmann's avatar
henrikburmann committed
    cancelDelete() {
      this.readyToDelete = false;
    },
    /**
     * 2 methods related to pagination. Updates page and updates
     * visible items on page.
     */
henrikburmann's avatar
henrikburmann committed
    updatePage(pageNumber) {
      this.currentPage = pageNumber;
      this.updateVisibleTodos();
    },
    updateVisibleTodos() {
      this.visibleItems = this.items.slice(
        this.currentPage * this.pageSize,
        this.currentPage * this.pageSize + this.pageSize
      );

      // if we have 0 visible items, go back a page
      if (this.visibleItems.length === 0 && this.currentPage > 0) {
        this.updatePage(this.currentPage - 1);
      }
    },
    goToDeleteItem(item) {
      this.chosenItem = item;
      this.readyToDelete = true;
    },
henrikburmann's avatar
henrikburmann committed
    async deleteItem() {
      await UserService.setListingToDeleted(this.chosenItem);
henrikburmann's avatar
henrikburmann committed
      this.$router.go(0);

    /**
     * This method triggers when search input field is changed
     */
henrikburmann's avatar
henrikburmann committed
    searchWritten: function () {
      if (this.search.length > 0) {
        this.showItems = false;
        this.showSearchedItems = true;
      } else {
        this.showItems = true;
        this.showSearchedItems = false;
      }
    },
  },

  /**
   * Gets userlistings and prepares the pagination by
   * updating the items to be visible.
   */
henrikburmann's avatar
henrikburmann committed
  async beforeMount() {
    await this.getUserListingsFromAPI();
    this.updateVisibleTodos();
  },
};
</script>

<style>
#headline {
  display: block;
  margin-top: 10px;
Erik Borgeteien Hansen's avatar
Erik Borgeteien Hansen committed
  margin-bottom: 10px;
henrikburmann's avatar
henrikburmann committed
  margin-left: 20px;
henrikburmann's avatar
henrikburmann committed
}
.cardContainer {
henrikburmann's avatar
henrikburmann committed
  position: relative;
}
.DotButton {
henrikburmann's avatar
henrikburmann committed
  position: absolute;
  right: 40px;
  bottom: 10px;
henrikburmann's avatar
henrikburmann committed
}
.options {
henrikburmann's avatar
henrikburmann committed
  position: absolute;
}
Erik Borgeteien Hansen's avatar
Erik Borgeteien Hansen committed
</style>