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