sutty-base-jekyll-theme/_packs/controllers/country_controller.js

102 lines
3.1 KiB
JavaScript
Raw Normal View History

2021-06-01 21:33:49 +00:00
import { CartBaseController } from './cart_base_controller'
/*
* Populates a country field where users can type to filter and select
* from a predefined list.
*/
export default class extends CartBaseController {
// All are required!
static targets = [ 'id', 'iso', 'list', 'name' ]
async connect () {
const countries = await this.countries()
countries.forEach(country => {
const option = document.createElement('option')
option.value = country.attributes.name
option.dataset.id = country.id
option.dataset.iso = country.attributes.iso
option.dataset.statesRequired = country.attributes.states_required
option.dataset.zipcodeRequired = country.attributes.zipcode_required
this.listTarget.appendChild(option)
})
2021-10-28 17:59:19 +00:00
const site = window.site
2021-06-01 21:33:49 +00:00
// Only allow names on this list
this.nameTarget.pattern = countries.map(x => x.attributes.name).join('|')
this.nameTarget.addEventListener('input', event => this.nameTarget.setCustomValidity(''))
this.nameTarget.addEventListener('invalid', event => this.nameTarget.setCustomValidity(site.i18n.countries.validation))
// When the input changes we update the actual value and also the
// state list via an Event
this.nameTarget.addEventListener('change', event => {
const value = this.nameTarget.value.trim()
if (value === '') return
const options = Array.from(this.nameTarget.list.options)
const option = options.find(x => x.value == value)
// TODO: If no option is found, mark the field as invalid
if (!option) return
this.idTarget.value = option.dataset.id
this.isoTarget.value = option.dataset.iso
this.idTarget.dispatchEvent(new Event('change'))
this.isoTarget.dispatchEvent(new Event('change'))
this.dispatchChangedEvent(option.dataset)
// XXX: Prevent mixing data
delete this.nameTarget.dataset.selectedState
delete this.nameTarget.dataset.selectedZipcode
})
// The input is disabled at this point
this.nameTarget.disabled = false
// Load data if the input is autocompleted
if (this.nameTarget.value.trim() !== '') this.nameTarget.dispatchEvent(new CustomEvent('change'))
}
/*
* Sends a `cart:country:update` event so other controllers can
* subscribe to changes.
*/
dispatchChangedEvent (data = {}) {
const event = new CustomEvent('cart:country:update', {
detail: {
id: this.idTarget.value,
iso: this.isoTarget.value,
group: this.data.get('group'),
selectedState: this.nameTarget.dataset.selectedState,
selectedZipcode: this.nameTarget.dataset.selectedZipcode,
data
}
})
window.dispatchEvent(event)
}
/*
* Fetch the country list from storage or from API
*/
async countries () {
const countries = JSON.parse(this.storageTemp.getItem('countries'))
if (countries) return countries
const response = await this.spree.countries.list()
// TODO: Show error message
if (!response.success()) return
this.storageTemp.setItem('countries', JSON.stringify(response.success().data))
return response.success().data
}
}