Source

components/shared/geocoding/AddressFormSelect.vue

<template lang="pug">
.afs-wrapper(@click="(e) => e.stopPropagation()")
  input(
    :placeholder="placeholder",
    :value="inputValue",
    readonly,
    @click="toggleCollapse"
  )
  .afs-form
    LocateAddressForm.afs-form-cmp(
      v-show="!collapsed",
      v-model="form",
      @valid="onFormValidate",
      @goBack="onFormReset",
      :isLoading="isLoading"
    )
</template>
<script>
import { getFormattedAddress } from '@/utils/address.js'
import LocateAddressForm from '@c/shared/geocoding/LocateAddressFormFeature/LocateAddressForm.vue'
import i18n from '@/i18n'
import { isUnitTest } from '@/utils/unit.js'
let createExitMixin = () => {}
if (!isUnitTest()) {
  createExitMixin = require('@/mixins/exit-mixin.ts').default
}

const componentInstances = {
  //{vm:null}
}

/**
 * Similar to LocateAddressFormFeature but the user is just select an address (without map interactions)
 * @namespace components
 * @category components
 * @subcategory shared/geocoding
 * @module AddressFormSelect
 */
export default {
  components: {
    LocateAddressForm,
  },
  mixins: [
    createExitMixin({
      onExitHandler(vm) {
        if (!vm.collapsed) {
          vm.collapsed = true
        }
      },
      bindClick: true,
    }),
  ],
  props: {
    value: {
      type: Object,
      default: () => ({}),
    },
    placeholder: {
      type: String,
      default: i18n.t('geocoding.locate_address_form_select.tooltip'),
    },
  },
  data() {
    return {
      collapsed: true,
      isLoading: false,
      form: {},
      result: {},
    }
  },
  computed: {
    inputValue() {
      return this.value.formatted || this.result?.formatted || ''
    },
  },
  created() {
    componentInstances[this._uid] = this
  },
  destroyed() {
    delete componentInstances[this._uid]
  },
  methods: {
    /**
     * Routing: Prevent two opened forms at the same time.
     * https://easyredmine.simpliciti.fr/issues/34367
     */
    collapseOthers() {
      Object.keys(componentInstances)
        .filter((k) => k != this._uid)
        .forEach((uid) => {
          let vm = componentInstances[uid]
          if (vm && !(vm._isDestroyed || vm._isBeingDestroyed)) {
            vm.collapsed = true
          }
        })
    },
    toggleCollapse() {
      let collapsed = !this.collapsed
      if (!collapsed) {
        this.collapseOthers()
      }
      this.collapsed = collapsed
    },
    onFormReset() {
      this.$emit('input', {})
      this.collapsed = true
      this.result = {}
    },
    async onFormValidate(event) {
      this.isLoading = true

      await this.$geocoding
        .forwardGeocoding({
          streetNumber: this.form.street_number,
          streetName: this.form.street_name,
          city: this.form.city,
          zipcode: this.form.postal_code,
          region: this.form.region,
          country: this.form.country,
        })
        .then(async (response) => {
          this.result = {
            lat: response.latitude,
            lng: response.longitude,
            formatted: getFormattedAddress(response, {
              streetNumber: 'streetNumber',
              streetName: 'streetName',
              zipCode: 'zipcode',
              city: 'city',
            }),
          }
          this.$emit('input', this.result)
          this.collapsed = true
        })
        .finally(() => {
          this.isLoading = false
        })
    },
  },
}
</script>
<style lang="scss" scoped>
.afs-form {
  position: relative;
  left: -100px;

  z-index: 100000000;
  top: -24px;
  & > div {
    padding: 15px;
  }
}
.afs-form-cmp {
  position: absolute;
  left: 0px;
  top: 10px;
  z-index: 10000;
  background-color: white;
  box-shadow: 10px 5px 11px rgb(0 0 0 / 8%);
}
input {
  border: 1px solid #e8e8e8;
  color: #adadad;
  margin-bottom: 10px;
  font-size: 14px;
  min-height: 40px;
  display: block;
  padding: 8px;
  width: -webkit-fill-available;
  font-family: 'Open Sans', sans-serif;
}
</style>