Covivo/mobicoop

View on GitHub
client/src/MobicoopBundle/Resources/assets/js/components/community/CommunityCreate.vue

Summary

Maintainability
Test Coverage
<template>
  <v-main>
    <!--SnackBar-->
    <v-snackbar
      v-model="snackbar"
      color="error"
      top
    >
      {{ snackError }}
      <v-btn
        color="white"
        text
        @click="snackbar = false"
      >
        <v-icon>mdi-close-circle-outline</v-icon>
      </v-btn>
    </v-snackbar>
    <v-container>
      <v-row justify="center">
        <v-col
          cols="12"
          md="8"
          xl="6"
          align="center"
        >
          <h1>{{ $t('title') }}</h1>
        </v-col>
      </v-row>
      <v-row
        justify="center"
        align="center"
      >
        <v-col
          cols="12"
          align="center"
        >
          <v-row justify="center">
            <v-col cols="6">
              <v-text-field
                v-model="name"
                :rules="nameRules"
                :label="$t('form.name.label')"
              />
            </v-col>
          </v-row>
          <v-row justify="center">
            <v-col cols="6">
              <v-text-field
                v-model="description"
                :rules="descriptionRules"
                :label="$t('form.description.label')"
                counter="255"
              />
            </v-col>
          </v-row>
          <v-row justify="center">
            <v-col cols="6">
              <v-textarea
                v-model="fullDescription"
                :rules="fullDescriptionRules"
                :label="$t('form.fullDescription.label')"
                rows="5"
                auto-grow
                clearable
                outlined
                counter="2500"
                row-height="24"
              />
            </v-col>
          </v-row>
          <v-row
            v-if="communityWithFreeCarpool"
            justify="center"
          >
            <v-col cols="6">
              <v-tooltip top>
                <template v-slot:activator="{ on, attrs }">
                  <span
                    v-bind="attrs"
                    v-on="on"
                  >
                    <v-switch
                      v-model="freeCarpool"
                      :label="$t('freeCarpool.label')"
                    />
                  </span>
                </template>
                <span>{{ $t('freeCarpool.tooltip') }}</span>
              </v-tooltip>
            </v-col>
          </v-row>
          <v-row justify="center">
            <v-col cols="6">
              <geocomplete
                :uri="geoSearchUrl"
                :results-order="geoCompleteResultsOrder"
                :palette="geoCompletePalette"
                :chip="geoCompleteChip"
                :label="$t('form.address.label')"
                @address-selected="addressSelected"
              />
            </v-col>
          </v-row>
          <v-row justify="center">
            <v-col cols="6">
              <v-tooltip
                left
                color="info"
                bottom
              >
                <template v-slot:activator="{ on }">
                  <v-text-field
                    v-model="domain"
                    :rules="domainRules"
                    :label="$t('form.domain.label')"
                    v-on="on"
                  />
                </template>
                <span>{{ $t('form.domain.tooltips') }}</span>
              </v-tooltip>
            </v-col>
          </v-row>
          <v-row justify="center">
            <v-col cols="6">
              <v-file-input
                ref="avatar"
                v-model="avatar"
                :rules="avatarRules"
                accept="image/png, image/jpeg, image/jpg"
                :label="$t('form.avatar.label')"
                prepend-icon="mdi-image"
                :hint="$t('form.avatar.minPxSize', { size: imageMinPxSize }) + ', ' + $t('form.avatar.maxMbSize', { size: imageMaxMbSize })"
                persistent-hint
                show-size
                @change="selectedAvatar"
              />
            </v-col>
          </v-row>
          <v-row justify="center">
            <v-col cols="6">
              <v-btn
                rounded
                color="primary"
                :disabled="!createButtonEnabled"
                :loading="loading"
                @click="createCommunity"
              >
                {{ $t('buttons.create.label') }}
              </v-btn>
            </v-col>
          </v-row>
        </v-col>
      </v-row>
    </v-container>
  </v-main>
</template>
<script>

import { messages_en, messages_fr, messages_eu, messages_nl } from "@translations/components/community/CommunityCreate/";
import Geocomplete from "@components/utilities/geography/Geocomplete";
import maxios from "@utils/maxios";

export default {
  i18n: {
    messages: {
      'en': messages_en,
      'nl': messages_nl,
      'fr': messages_fr,
      'eu': messages_eu
    },
  },
  components: {
    Geocomplete
  },
  props: {
    user: {
      type: Object,
      default: null
    },
    community: {
      type: Array,
      default: null
    },
    geoSearchUrl: {
      type: String,
      default: null
    },
    imageMinPxSize: {
      type: Number,
      default: null
    },
    imageMaxMbSize: {
      type: Number,
      default: null
    },
    geoCompleteResultsOrder: {
      type: Array,
      default: null
    },
    geoCompletePalette: {
      type: Object,
      default: () => ({})
    },
    geoCompleteChip: {
      type: Boolean,
      default: false
    },
    communityWithFreeCarpool: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      avatarRules: [
        v => !!v || this.$t("form.avatar.required"),
        v => !v || v.size < this.imageMaxMbSize * 1024 * 1024 || this.$t("form.avatar.mbSize", { size: this.imageMaxMbSize }),
        v => !v || this.avatarHeight >= this.imageMinPxSize || this.$t("form.avatar.pxSize", { size: this.imageMinPxSize, height: this.avatarHeight, width: this.avatarWidth }),
        v => !v || this.avatarWidth >= this.imageMinPxSize || this.$t("form.avatar.pxSize", { size: this.imageMinPxSize, height: this.avatarHeight, width: this.avatarWidth }),
      ],
      communityAddress: null,
      name: null,
      nameRules: [
        v => !!v || this.$t("form.name.required"),
      ],
      description: null,
      descriptionRules: [
        v => !!v || this.$t("form.description.required"),
      ],
      fullDescription: null,
      fullDescriptionRules: [
        v => !!v || this.$t("form.fullDescription.required"),
      ],
      avatar: null,
      avatarHeight: null,
      avatarWidth: null,
      loading: false,
      snackError: null,
      snackbar: false,
      domain: null,
      domainRules: [
        v => !v || /([\w+-]*\.[\w+]*$)/.test(v) || this.$t("form.domain.error")
      ],
      freeCarpool: false
    }
  },
  computed: {
    createButtonEnabled() {
      if (
        (this.avatarHeight && this.avatarHeight < this.imageMinPxSize) ||
        (this.avatarWidth && this.avatarWidth < this.imageMinPxSize)
      ) {
        return false;
      }
      if (this.avatar && (this.avatar.size > this.imageMaxMbSize * 1024 * 1024)) {
        return false;
      }
      return true;
    }
  },
  methods: {
    addressSelected: function (address) {
      this.communityAddress = address;
    },
    createCommunity() {
      this.loading = true;
      if (this.name && this.description && this.fullDescription && this.avatar && this.communityAddress) {
        let newCommunity = new FormData();
        newCommunity.append("name", this.name);
        newCommunity.append("description", this.description);
        newCommunity.append("fullDescription", this.fullDescription);
        newCommunity.append("avatar", this.avatar);
        newCommunity.append("address", JSON.stringify(this.communityAddress));
        newCommunity.append('freeCarpool', this.freeCarpool);
        if (this.domain) newCommunity.append("domain", this.domain);

        maxios
          .post(this.$t('buttons.create.route'), newCommunity, {
            headers: {
              'content-type': 'multipart/form-data'
            }
          })
          .then(res => {
            if (res.data.includes('error')) {
              this.snackError = this.$t(res.data)
              this.snackbar = true;
              this.loading = false;
            }
            else window.location.href = this.$t('redirect.route');
          });
      } else {
        this.snackError = this.$t('error.community.required')
        this.snackbar = true;
        this.loading = false;
      }
    },
    selectedAvatar() {
      this.avatarWidth = null;
      this.avatarHeight = null;

      if (!this.avatar) return;
      let reader = new FileReader();

      reader.readAsDataURL(this.avatar);
      reader.onload = evt => {
        let self = this;
        let img = new Image();
        img.onload = () => {
          self.avatarHeight = img.height;
          self.avatarWidth = img.width;
          self.$refs.avatar.validate()
        }
        img.src = evt.target.result;
      }

    }
  }
}
</script>

<style></style>