2019-09-20 20:05:27 +02:00

218 lines
5.4 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')"
/>
<ds-input
id="slug"
model="slug"
icon="at"
:label="$t('settings.data.labelSlug')"
@input.native="validateSlug"
/>
<ds-text v-if="!slugAvailable" color="danger">
{{ $t('settings.validation.slug.alreadyTaken') }}
</ds-text>
<!-- 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="loadingGeo"
@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"
:disabled="!slugAvailable"
type="submit"
:loading="loadingData"
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 { checkSlugAvailableQuery } from '~/graphql/User.js'
import { debounce } from 'lodash'
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!, $slug: String, $name: String, $locationName: String, $about: String) {
UpdateUser(id: $id, slug: $slug, name: $name, locationName: $locationName, about: $about) {
id
slug
name
locationName
about
}
}
`
export default {
data() {
return {
axiosSource: null,
cities: [],
loadingData: false,
loadingGeo: false,
formData: {},
slugAvailable: true,
}
},
computed: {
...mapGetters({
currentUser: 'auth/user',
}),
form: {
get: function() {
const { name, slug, locationName, about } = this.currentUser
return { name, slug, locationName, about }
},
set: function(formData) {
this.formData = formData
},
},
},
created() {
this.validateSlug = debounce(async () => {
const variables = { slug: this.formData.slug }
const {
data: { User },
} = await this.$apollo.query({ query: checkSlugAvailableQuery, variables })
const existingSlug = User && User[0] && User[0].slug
this.slugAvailable = !existingSlug || existingSlug === this.currentUser.slug
}, 500)
},
methods: {
...mapMutations({
setCurrentUser: 'auth/SET_USER',
}),
async submit() {
this.loadingData = true
const { name, slug, about } = this.formData
let { locationName } = this.formData || this.currentUser
locationName = locationName && (locationName['label'] || locationName)
try {
await this.$apollo.mutate({
mutation,
variables: {
id: this.currentUser.id,
name,
slug,
locationName,
about,
},
update: (store, { data: { UpdateUser } }) => {
const { name, slug, locationName, about } = UpdateUser
this.setCurrentUser({
...this.currentUser,
name,
slug,
locationName,
about,
})
},
})
this.$toast.success(this.$t('settings.data.success'))
} catch (err) {
this.$toast.error(err.message)
} finally {
this.loadingData = 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.loadingGeo = 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.loadingGeo = false
})
},
},
}
</script>