Source

components/shared/geocoding/LocateAddressResults.vue

<template>
  <div>
    <div class="wrapper">
      <b-col class="mt-2">
        <b-row v-if="results.title" class="pb-2 section-title">
          {{ $t(`popup.form_builder.sections.${results.title}`) }}
        </b-row>
        <div
          v-for="(row, index) in results.rows"
          :key="index"
          class="row-item"
          :class="{ selected: isSelected(row) }"
          @click="$emit('select', row.item)"
        >
          <b-row class="m-0 p-0">
            <div class="col-1 flex-centered p-0 m-0">
              <b-icon icon="search" @click.prevent="locateAddress(row)" />
            </div>
            <div class="col-11 p-0 m-0">
              {{ row.value }}
            </div>
          </b-row>
        </div>
      </b-col>
    </div>

    <NearbyVehiclesFeature
      v-if="hasRightToNearbyVehiclesFeature"
      :lat="selectedItemLat"
      :lng="selectedItemLng"
      :formatted-address="formattedAddress"
      class="mt-5"
    />

    <!-- Vehicules proches: Rayon de recherche en KM :sections="sections" -->
    <form-builder
      has-cancel-btn
      :cancel-text="$t('buttons.return')"
      has-preview-btn
      class="mt-2 wrapper"
      @update-column-value="setColumnValue"
      @go-back="goBackForm"
      @preview="onPreview"
    />
  </div>
</template>

<script>
import FormBuilder from '../Builders/FormBuilder'
import NearbyVehiclesFeature, {
  useNearbyVehicles,
} from '@c/nearby_vehicles/NearbyVehiclesFeature.vue'
import { reactive, computed } from 'vue'
import { useRightsPlugin } from '@/mixins/rights-mixin.js'
const { hasFeatureRight, rightsTable } = useRightsPlugin()
const { updateNearbyVehicles, clearNearbyVehicles } = useNearbyVehicles()
const moduleContext = reactive({
  formattedAddress: '',
  reset() {
    this.formattedAddress = ''
  },
})

export function useLocateAddressResults() {
  return {
    /**
     * Used by NearbyVehiclesFeature
     */
    currentFormattedAddress: computed(() => moduleContext.formattedAddress),
  }
}

/**
 * @namespace components
 * @category components
 * @subcategory shared/geocoding
 * @module LocateAddressResults
 */
export default {
  name: 'LocateAddressResults',
  components: {
    FormBuilder,
    NearbyVehiclesFeature,
  },
  props: {
    selectedItem: {
      type: Object,
      default: () => ({}),
    },
    title: {
      type: String,
      default: 'common.map.popup.address_locate',
    },
    hasForm: {
      type: Boolean,
      default: false,
    },
    items: {
      type: Array,
      default: () => [
        { value: 'Avignon France' },
        { value: 'Aubignan France' },
      ],
    },
  },
  data() {
    return {
      sections: [
        {
          name: 'vehicle_section',
          title: 'vehicle_section_title',
          header: false,
          collapsable: false,
          rows: [
            {
              id: 'vehicle_row',
              columns: [{ label: 'vehicle_radius', type: 'number', value: '' }],
            },
          ],
        },
      ],
    }
  },
  computed: {
    hasRightToNearbyVehiclesFeature() {
      return hasFeatureRight(rightsTable.nearby_vehicles_feature)
    },
    results() {
      return {
        title: 'results_address_vehicle_section_title',
        rows: [...this.items],
      }
    },
    selectedItemLat() {
      return this.selectedItem.lat || this.selectedItem.latitude
    },
    selectedItemLng() {
      return this.selectedItem.lng || this.selectedItem.longitude
    },
    formattedAddress() {
      return this.selectedItem.formatted || ''
    },
  },
  watch: {
    selectedItem: {
      handler() {
        moduleContext.formattedAddress = this.selectedItem.formatted || ''
      },
      deep: true,
      immediate: true,
    },
  },
  destroyed() {
    moduleContext.reset()
  },
  methods: {
    onPreview() {
      //Nearby vehicles -> Trigger the API call and render vehicles in the map
      updateNearbyVehicles()

      this.$emit('preview')
    },
    isSelected(row) {
      return Object.is(this.selectedItem || {}, row.item)
    },

    goBackForm(event) {
      clearNearbyVehicles()
      this.resetSectionsValues()
      this.$emit('goBack')
    },
    locateAddress(event) {
      this.$emit('select', event.item)
    },
    setColumnValue(options) {
      let column = null
      this.sections.find((section) => {
        !!section.rows.find((row) => {
          column = row.columns.find((column) => column.label === options.label)
          return !!column
        })
      })
      if (column) column.value = options.event
    },
    resetSectionsValues() {
      const rows = this.sections.flatMap((section) =>
        section.rows.filter((row) => row.columns.length > 0)
      )
      rows.forEach((row) => {
        row.columns.forEach((column) => {
          column.value = ''
        })
      })
    },
  },
}
</script>

<style lang="scss" scoped>
.wrapper {
  font-size: 12px;
}
.map-popup-wrapper {
  border-radius: 5px;
  border: 1px var(--color-denim) solid;
}
.section-title {
  color: var(--color-denim);
  font-size: 14px;
  font-weight: bold;
}
.result-icon {
  color: var(--color-denim);
  cursor: pointer;
}
.flex-centered {
  align-items: center;
  justify-content: center;
  display: flex;
}
.selected {
  background: rgba(0, 0, 0, 0.05);
}
.row-item {
  cursor: pointer;
  font-size: 14px;
  margin-bottom: 15px;
}
</style>