summaryrefslogtreecommitdiffstats
path: root/browser/components/payments/res/containers/payment-method-picker.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/payments/res/containers/payment-method-picker.js')
-rw-r--r--browser/components/payments/res/containers/payment-method-picker.js199
1 files changed, 199 insertions, 0 deletions
diff --git a/browser/components/payments/res/containers/payment-method-picker.js b/browser/components/payments/res/containers/payment-method-picker.js
new file mode 100644
index 0000000000..3693d352a5
--- /dev/null
+++ b/browser/components/payments/res/containers/payment-method-picker.js
@@ -0,0 +1,199 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import BasicCardOption from "../components/basic-card-option.js";
+import CscInput from "../components/csc-input.js";
+import HandleEventMixin from "../mixins/HandleEventMixin.js";
+import RichPicker from "./rich-picker.js";
+import paymentRequest from "../paymentRequest.js";
+
+/* import-globals-from ../unprivileged-fallbacks.js */
+
+/**
+ * <payment-method-picker></payment-method-picker>
+ * Container around add/edit links and <rich-select> with
+ * <basic-card-option> listening to savedBasicCards.
+ */
+
+export default class PaymentMethodPicker extends HandleEventMixin(RichPicker) {
+ constructor() {
+ super();
+ this.dropdown.setAttribute("option-type", "basic-card-option");
+ this.securityCodeInput = new CscInput();
+ this.securityCodeInput.className = "security-code-container";
+ this.securityCodeInput.placeholder = this.dataset.cscPlaceholder;
+ this.securityCodeInput.backTooltip = this.dataset.cscBackTooltip;
+ this.securityCodeInput.frontTooltip = this.dataset.cscFrontTooltip;
+ this.securityCodeInput.addEventListener("change", this);
+ this.securityCodeInput.addEventListener("input", this);
+ }
+
+ connectedCallback() {
+ super.connectedCallback();
+ this.dropdown.after(this.securityCodeInput);
+ }
+
+ get fieldNames() {
+ let fieldNames = [...BasicCardOption.recordAttributes];
+ return fieldNames;
+ }
+
+ render(state) {
+ let basicCards = paymentRequest.getBasicCards(state);
+ let desiredOptions = [];
+ for (let [guid, basicCard] of Object.entries(basicCards)) {
+ let optionEl = this.dropdown.getOptionByValue(guid);
+ if (!optionEl) {
+ optionEl = document.createElement("option");
+ optionEl.value = guid;
+ }
+
+ for (let key of BasicCardOption.recordAttributes) {
+ let val = basicCard[key];
+ if (val) {
+ optionEl.setAttribute(key, val);
+ } else {
+ optionEl.removeAttribute(key);
+ }
+ }
+
+ optionEl.textContent = BasicCardOption.formatSingleLineLabel(basicCard);
+ desiredOptions.push(optionEl);
+ }
+
+ this.dropdown.popupBox.textContent = "";
+ for (let option of desiredOptions) {
+ this.dropdown.popupBox.appendChild(option);
+ }
+
+ // Update selectedness after the options are updated
+ let selectedPaymentCardGUID = state[this.selectedStateKey];
+ if (selectedPaymentCardGUID) {
+ this.dropdown.value = selectedPaymentCardGUID;
+
+ if (selectedPaymentCardGUID !== this.dropdown.value) {
+ throw new Error(
+ `The option ${selectedPaymentCardGUID} ` +
+ `does not exist in the payment method picker`
+ );
+ }
+ } else {
+ this.dropdown.value = "";
+ }
+
+ let securityCodeState = state[this.selectedStateKey + "SecurityCode"];
+ if (
+ securityCodeState &&
+ securityCodeState != this.securityCodeInput.value
+ ) {
+ this.securityCodeInput.defaultValue = securityCodeState;
+ }
+
+ let selectedCardType =
+ (basicCards[selectedPaymentCardGUID] &&
+ basicCards[selectedPaymentCardGUID]["cc-type"]) ||
+ "";
+ this.securityCodeInput.cardType = selectedCardType;
+
+ super.render(state);
+ }
+
+ errorForSelectedOption(state) {
+ let superError = super.errorForSelectedOption(state);
+ if (superError) {
+ return superError;
+ }
+ let selectedOption = this.selectedOption;
+ if (!selectedOption) {
+ return "";
+ }
+
+ let basicCardMethod = state.request.paymentMethods.find(
+ method => method.supportedMethods == "basic-card"
+ );
+ let merchantNetworks =
+ basicCardMethod &&
+ basicCardMethod.data &&
+ basicCardMethod.data.supportedNetworks;
+ let acceptedNetworks =
+ merchantNetworks || PaymentDialogUtils.getCreditCardNetworks();
+ let selectedCard = paymentRequest.getBasicCards(state)[
+ selectedOption.value
+ ];
+ let isSupported =
+ selectedCard["cc-type"] &&
+ acceptedNetworks.includes(selectedCard["cc-type"]);
+ return isSupported ? "" : this.dataset.invalidLabel;
+ }
+
+ get selectedStateKey() {
+ return this.getAttribute("selected-state-key");
+ }
+
+ onInput(event) {
+ this.onInputOrChange(event);
+ }
+
+ onChange(event) {
+ this.onInputOrChange(event);
+ }
+
+ onInputOrChange({ currentTarget }) {
+ let selectedKey = this.selectedStateKey;
+ let stateChange = {};
+
+ if (!selectedKey) {
+ return;
+ }
+
+ switch (currentTarget) {
+ case this.dropdown: {
+ stateChange[selectedKey] = this.dropdown.value;
+ break;
+ }
+ case this.securityCodeInput: {
+ stateChange[
+ selectedKey + "SecurityCode"
+ ] = this.securityCodeInput.value;
+ break;
+ }
+ default: {
+ return;
+ }
+ }
+
+ this.requestStore.setState(stateChange);
+ }
+
+ onClick({ target }) {
+ let nextState = {
+ page: {
+ id: "basic-card-page",
+ },
+ "basic-card-page": {
+ selectedStateKey: this.selectedStateKey,
+ },
+ };
+
+ switch (target) {
+ case this.addLink: {
+ nextState["basic-card-page"].guid = null;
+ break;
+ }
+ case this.editLink: {
+ let state = this.requestStore.getState();
+ let selectedPaymentCardGUID = state[this.selectedStateKey];
+ nextState["basic-card-page"].guid = selectedPaymentCardGUID;
+ break;
+ }
+ default: {
+ throw new Error("Unexpected onClick");
+ }
+ }
+
+ this.requestStore.setState(nextState);
+ }
+}
+
+customElements.define("payment-method-picker", PaymentMethodPicker);