207 lines
4.6 KiB
Vue

<template>
<ds-form
v-model="form"
@submit="submit"
>
<ds-card :header="$t('settings.data.name')">
<ds-input
id="name"
model="name"
icon="user"
:label="$t('settings.data.labelName')"
:placeholder="$t('settings.data.namePlaceholder')"
/>
<!-- eslint-disable vue/use-v-on-exact -->
<ds-select
id="city"
model="locationName"
icon="map-marker"
:options="cities"
:label="$t('settings.data.labelCity')"
:placeholder="$t('settings.data.labelCity')"
:loading="loading"
@input.native="handleCityInput"
/>
<!-- eslint-enable vue/use-v-on-exact -->
<ds-input
id="bio"
model="about"
type="textarea"
rows="3"
:label="$t('settings.data.labelBio')"
:placeholder="$t('settings.data.labelBio')"
/>
<template slot="footer">
<ds-button
style="float: right;"
icon="check"
type="submit"
:loading="sending"
primary
>
{{ $t('actions.save') }}
</ds-button>
</template>
</ds-card>
</ds-form>
</template>
<script>
import gql from 'graphql-tag'
import { mapGetters, mapMutations } from 'vuex'
import { CancelToken } from 'axios'
import find from 'lodash/find'
let timeout
const mapboxToken = process.env.MAPBOX_TOKEN
const query = gql`
query getUser($id: ID) {
User(id: $id) {
id
name
locationName
about
}
}
`
const mutation = gql`
mutation($id: ID!, $name: String, $locationName: String, $about: String) {
UpdateUser(
id: $id
name: $name
locationName: $locationName
about: $about
) {
id
name
locationName
about
}
}
`
export default {
data() {
return {
axiosSource: null,
cities: [],
sending: false,
loading: false,
formData: {}
}
},
computed: {
...mapGetters({
currentUser: 'auth/user'
}),
form: {
get: function() {
const { name, locationName, about } = this.currentUser
return { name, locationName, about }
},
set: function(formData) {
this.formData = formData
}
}
},
methods: {
...mapMutations({
setCurrentUser: 'auth/SET_USER'
}),
submit() {
this.sending = true
const { name, about } = this.formData
let { locationName } = this.formData
locationName = locationName && (locationName['label'] || locationName)
this.$apollo
.mutate({
mutation,
variables: {
id: this.currentUser.id,
name,
locationName,
about
},
update: (store, { data: { UpdateUser } }) => {
const { name, locationName, about } = UpdateUser
this.setCurrentUser({
...this.currentUser,
name,
locationName,
about
})
}
})
.then(data => {
this.$toast.success('Updated user')
})
.catch(err => {
this.$toast.error(err.message)
})
.finally(() => {
this.sending = false
})
},
handleCityInput(value) {
clearTimeout(timeout)
timeout = setTimeout(() => this.requestGeoData(value), 500)
},
processCityResults(res) {
if (
!res ||
!res.data ||
!res.data.features ||
!res.data.features.length
) {
return []
}
let output = []
res.data.features.forEach(item => {
output.push({
label: item.place_name,
value: item.place_name,
id: item.id
})
})
return output
},
requestGeoData(e) {
if (this.axiosSource) {
// cancel last request
this.axiosSource.cancel()
}
const value = e.target ? e.target.value.trim() : ''
if (value === '' || value.length < 3) {
this.cities = []
return
}
this.loading = true
this.axiosSource = CancelToken.source()
const place = encodeURIComponent(value)
const lang = this.$i18n.locale()
this.$axios
.get(
`https://api.mapbox.com/geocoding/v5/mapbox.places/${place}.json?access_token=${mapboxToken}&types=region,place,country&language=${lang}`,
{
cancelToken: this.axiosSource.token
}
)
.then(res => {
this.cities = this.processCityResults(res)
})
.finally(() => {
this.loading = false
})
}
}
}
</script>