Skip to content
Snippets Groups Projects
NewItemForm.vue 12.5 KiB
Newer Older
<template>
  <div
    class="md:ring-1 ring-gray-300 rounded-xl overflow-hidden mx-auto mb-auto max-w-md w-full p-4"
  >
    <!-- Component heading -->
Gilgard's avatar
Gilgard committed
    <h3 class="text-xl font-medium text-center text-primary-light mt-4 mb-8">
      Opprett ny utleie
    </h3>

    <!-- Title -->
    <div class="mb-6" :class="{ error: v$.item.title.$errors.length }">
      <label
        class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
Zara Mudassar's avatar
Zara Mudassar committed
        id="titleLabel"
      <input
        type="text"
        id="title"
Gilgard's avatar
Gilgard committed
        class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light"
        v-model="v$.item.title.$model"
      <!-- error message for title-->
      <div
        class="text-error-medium"
        v-for="(error, index) of v$.item.title.$errors"
        :key="index"
      >
        <div class="text-error-medium text-sm">
          {{ error.$message }}
        </div>
      </div>
    </div>

Zara Mudassar's avatar
Zara Mudassar committed
    <!-- Select category -->
    <div class="mb-6">
      <label
henrikburmann's avatar
henrikburmann committed
        class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400"
        id="selectCategoryLabel"
        >Kategori</label
Zara Mudassar's avatar
Zara Mudassar committed
      >
      <select
henrikburmann's avatar
henrikburmann committed
        v-model="v$.item.select.$model"
        id="categories"
        class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light"
Zara Mudassar's avatar
Zara Mudassar committed
      >
        <option class="text-gray-400" value="" disabled selected>
          Velg en kategori
        </option>
        <option
henrikburmann's avatar
henrikburmann committed
          v-for="category in categories"
          :key="category"
          class="text-gray-900 text-sm"
Zara Mudassar's avatar
Zara Mudassar committed
        >
          {{ category }}
        </option>
      </select>

      <!-- error message for select box -->
      <div
        class="text-error-medium"
henrikburmann's avatar
henrikburmann committed
        v-for="(error, index) of v$.item.select.$errors"
        :key="index"
Zara Mudassar's avatar
Zara Mudassar committed
      >
        <div class="text-error-medium text-sm">
Zara Mudassar's avatar
Zara Mudassar committed
          {{ error.$message }}
        </div>
      </div>
    </div>

    <!-- Grupper -->
Zara Mudassar's avatar
Zara Mudassar committed
    <div class="mb-6">
henrikburmann's avatar
henrikburmann committed
      <label class="block text-sm font-medium text-gray-900 dark:text-gray-400"
        >Grupper</label
      >
Titus Netland's avatar
Titus Netland committed
      <div
Gilgard's avatar
Gilgard committed
        class="overflow-auto w-full max-h-32 mt-2 text-base list-none bg-white rounded divide-y divide-gray-100 dark:bg-gray-700"
Zara Mudassar's avatar
Zara Mudassar committed
      >
Titus Netland's avatar
Titus Netland committed
        <ul class="py-1" aria-labelledby="dropdownDefault">
          <li>
            <div class="form-check" v-for="group in groups" :key="group">
              <input
henrikburmann's avatar
henrikburmann committed
                class="form-check-input appearance-none h-4 w-4 border border-gray-300 rounded-sm bg-white checked:bg-primary-medium focus:outline-none transition duration-200 mt-1 align-top bg-no-repeat bg-center bg-contain float-left mr-2 cursor-pointer"
                type="checkbox"
                :value="group.communityId"
                @change="onChangeGroup($event)"
              />
Titus Netland's avatar
Titus Netland committed
              <label class="form-check-label inline-block text-gray-800">
                {{ group.name }}
              </label>
            </div>
          </li>
        </ul>
      </div>
      <!-- Error message for community -->
Erik Borgeteien Hansen's avatar
Erik Borgeteien Hansen committed
      <label class="text-error-medium text-sm block">{{
        groupErrorMessage
      }}</label>
Titus Netland's avatar
Titus Netland committed
    </div>
    <div class="mb-6 mt-4" :class="{ error: v$.item.price.$errors.length }">
      <label
        class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
Titus Netland's avatar
Titus Netland committed
        >Pris per dag</label
        type="number"
        v-model="v$.item.price.$model"
        id="price"
Gilgard's avatar
Gilgard committed
        class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light"
        required
      />

      <!-- error message for price -->
      <div
        class="text-error-medium"
        v-for="(error, index) of v$.item.price.$errors"
        :key="index"
      >
        <div class="text-error-medium text-sm">
          {{ error.$message }}
        </div>
      </div>
    </div>

    <!-- Description -->
    <div class="mb-6" :class="{ error: v$.item.description.$errors.length }">
      <label
        class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400"
        >Beskrivelse</label
      >
      <textarea
        id="description"
        rows="4"
        v-model="v$.item.description.$model"
Gilgard's avatar
Gilgard committed
        class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light"
      <!-- error message for description -->
      <div
        class="text-error-medium"
        v-for="(error, index) of v$.item.description.$errors"
        :key="index"
      >
        <div class="text-error-medium text-sm">
          {{ error.$message }}
        </div>
      </div>
    </div>

Zara Mudassar's avatar
Zara Mudassar committed
    <!-- Address -->
    <div class="mb-6" :class="{ error: v$.item.address.$errors.length }">
      <label
        class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
        id="addressLabel"
Zara Mudassar's avatar
Zara Mudassar committed
      <input
Gilgard's avatar
Gilgard committed
        class="block w-full px-4 py-2 mt-2 text-gray-700 placeholder-gray-500 bg-white border rounded-md dark:bg-gray-800 dark:border-gray-600 dark:placeholder-gray-400 focus:border-primary-light dark:focus:border-primary-light focus:ring-opacity-40 focus:outline-none focus:ring focus:ring-primary-light"
        v-model="v$.item.address.$model"
        id="adress"
        required
Zara Mudassar's avatar
Zara Mudassar committed
      />

      <!-- error message for address-->
      <div
        class="text-error-medium"
        v-for="(error, index) of v$.item.address.$errors"
        :key="index"
Zara Mudassar's avatar
Zara Mudassar committed
      >
        <div class="text-error-medium text-sm">
Zara Mudassar's avatar
Zara Mudassar committed
          {{ error.$message }}
        </div>
      </div>
    </div>

    <!-- Images -->
    <div>
      <label
        class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-400"
        Bilder (bildene må være .png)

      <input
        type="file"
        ref="file"
        style="display: none"
        accept="image/png"
Gilgard's avatar
Gilgard committed
      <colored-button :text="'Velg bilde'" @click="$refs.file.click()" />
      <div v-for="image in item.images" :key="image" class="m-2">
Gilgard's avatar
Gilgard committed
        <form-image-display :image="image" @remove="removeImage(image)" />
      </div>
    </div>

    <!-- Save item button -->
    <div class="float-right">
Gilgard's avatar
Gilgard committed
      <colored-button :text="'Lagre'" @click="saveClicked" id="saveButton" />
</template>

<script>
import useVuelidate from "@vuelidate/core";
Zara Mudassar's avatar
Zara Mudassar committed
import { parseUserFromToken } from "@/utils/token-utils";
Gilgard's avatar
Gilgard committed
import ListingService from "@/services/listing.service";
import CommunityService from "@/services/community.service";
import ImageService from "@/services/image.service";
import ColoredButton from "@/components/BaseComponents/ColoredButton";
import FormImageDisplay from "@/components/BaseComponents/FormImageDisplay.vue";
import {
  required,
  helpers,
  maxLength,
  between,
  minLength,
} from "@vuelidate/validators";

export default {
Gilgard's avatar
Gilgard committed
  components: {
Gilgard's avatar
Gilgard committed
    ColoredButton,
    FormImageDisplay,
  setup() {
    return { v$: useVuelidate() };
  },

  validations() {
    return {
      item: {
        title: {
Zara Mudassar's avatar
Zara Mudassar committed
          required: helpers.withMessage(
            () => "Tittelen kan ikke være tom",
            required
Zara Mudassar's avatar
Zara Mudassar committed
          ),
          max: helpers.withMessage(
            () => `Tittelen kan inneholde max 50 tegn`,
            maxLength(50)
          ),
        },
        description: {
Zara Mudassar's avatar
Zara Mudassar committed
          required: helpers.withMessage(
            () => "Beskrivelsen kan ikke være tom",
            required
Zara Mudassar's avatar
Zara Mudassar committed
          ),
          max: helpers.withMessage(
            () => `Beskrivelsen kan inneholde max 200 tegn`,
            maxLength(200)
          ),
          min: helpers.withMessage(
            () => `Beskrivelsen kan ikke være tom`,
            minLength(0)
          ),
        },
        price: {
          required,
          between: helpers.withMessage(
            () => `Leieprisen kan ikke være større enn 25000`,
            between(0, 25000)
          ),
        },
        select: {
          required: helpers.withMessage(() => `Velg en kategori`, required),
        },
Zara Mudassar's avatar
Zara Mudassar committed
        address: {
          required: helpers.withMessage(
            () => "Addressen kan ikke være tom",
            required
Zara Mudassar's avatar
Zara Mudassar committed
          ),
          max: helpers.withMessage(
            () => `Addressen kan inneholde max 50 tegn`,
            maxLength(50)
Zara Mudassar's avatar
Zara Mudassar committed
          ),
        },

  data() {
    return {
      item: {
        title: "",
        description: "",
Zara Mudassar's avatar
Zara Mudassar committed
        address: "",
        price: "",
        category: "",
        type: "",
        images: [],
Zara Mudassar's avatar
Zara Mudassar committed
        userId: -1,
        selectedGroupId: -1,
        selectedGroups: [],
      //Kategorier skal legges inn ved api/hente fra db, her må det endres etterhvert
Gilgard's avatar
Gilgard committed
      categories: [
        "Antikviteter og kunst",
        "Dyr og utstyr",
        "Elektronikk og hvitevarer",
        "Foreldre og barn",
        "Fritid, hobby og underholdning",
        "Hage, oppussing og hus",
        "Klær, kosmetikk og tilbehør",
        "Møbler og interiør",
        "Næringsvirksomhet",
        "Sport og friluftsliv",
        "Utstyr til bil, båt og MC",
      ],
henrikburmann's avatar
henrikburmann committed
      groupErrorMessage: "",
    checkValidation: function () {
      this.v$.item.$touch();
      if (this.v$.item.$invalid || this.item.selectedGroups.length === 0) {
henrikburmann's avatar
henrikburmann committed
        if (this.item.selectedGroups.length === 0) {
          this.groupErrorMessage = "Velg gruppe/grupper";
        }
    async saveClicked() {
      if (this.checkValidation()) {
Zara Mudassar's avatar
Zara Mudassar committed
        this.checkUser();
Zara Mudassar's avatar
Zara Mudassar committed
        const itemInfo = {
          title: this.item.title,
          description: this.item.description,
          pricePerDay: this.item.price,
          address: this.item.address,
          userID: this.item.userId,
Gilgard's avatar
Gilgard committed
          categoryNames: [this.item.select],
          communityIDs: this.item.selectedGroups,
Zara Mudassar's avatar
Zara Mudassar committed
        };
Gilgard's avatar
Gilgard committed
        await ListingService.postNewItem(itemInfo);
Gilgard's avatar
Gilgard committed
        await ImageService.PostImagesArrayToListing(this.item.images);
henrikburmann's avatar
henrikburmann committed
        this.$router.push("/");
    checkUser: async function () {
Zara Mudassar's avatar
Zara Mudassar committed
      let user = parseUserFromToken(this.$store.state.user.token);
      this.item.userId = parseInt(user.accountId);
    },

    addImage: async function (event) {
      var that = this;
      let image = event.target.files[0];
      let fileReader = new FileReader();
      fileReader.onloadend = async function () {
        const res = fileReader.result;
Gilgard's avatar
Gilgard committed
        const id = await ImageService.postNewImage(res);
Gilgard's avatar
Gilgard committed

        const API_URL = process.env.VUE_APP_BASEURL;
Gilgard's avatar
Gilgard committed
        that.item.images.push(API_URL + "images/" + id);
      };
      fileReader.readAsArrayBuffer(image);
henrikburmann's avatar
henrikburmann committed
    onChangeGroup: function (e) {
      this.selectedGroupId = e.target.value;
      let alreadyInGroupList = false;

      for (let i = 0; i <= this.item.selectedGroups.length; i++) {
        if (this.selectedGroupId == this.item.selectedGroups[i]) {
          const index = this.item.selectedGroups.indexOf(this.selectedGroupId);
          if (index > -1) {
            this.item.selectedGroups.splice(index, 1);
          }
          alreadyInGroupList = true;
        }
      }

henrikburmann's avatar
henrikburmann committed
      if (!alreadyInGroupList) {
        this.item.selectedGroups.push(this.selectedGroupId);
        this.groupErrorMessage = "";
      }
Gilgard's avatar
Gilgard committed

    removeImage(image) {
      let newImages = [];
      for (let i in this.item.images) {
        if (this.item.images[i] != image) {
          newImages.push(this.item.images[i]);
        }
      }
      this.item.images = newImages;
    },
Gilgard's avatar
Gilgard committed
  async beforeMount() {
    this.groups = await CommunityService.getUserCommunities();
henrikburmann's avatar
henrikburmann committed
  },