import template from './checkout.component.html';
import { CheckoutService } from '../../services/checkout.service';
class ExtraField {
autocomplete: string;
isRequired: boolean;
label: string;
value: string | Array;
constructor(
label: string,
isRequired = false,
value = '',
autocomplete = 'off'
) {
this.label = label;
this.value = value;
this.isRequired = isRequired;
this.autocomplete = autocomplete;
}
}
export const CheckoutComponent: ng.IComponentOptions = {
bindings: {
poPrefix: '@',
},
template,
controller,
};
controller.$inject = ['$cookies', '$location', 'Checkout', 'User', 'Utils'];
function controller(
$cookies: ng.cookies.ICookiesService,
$location: ng.ILocationService,
Checkout: CheckoutService,
User,
Utils
) {
const vm = this;
this.hasAPIKey = localized.settings.general.api_key;
this.pageUrls = {
catalog: Utils.getPageUrl('catalog'),
login: Utils.getPageUrl('login', {
redirect_to: $location.path(),
}),
register: Utils.getPageUrl('register'),
savedCarts: Utils.getPageUrl('saved-carts'),
};
this.$onInit = () => {
if (this.hasAPIKey && User.isAuthed) {
setAddresses();
vm.productSlug =
localized.settings.general.product_slug || 'products';
vm.isSignedIn = User.isAuthed && User.email;
this.getCheckout();
}
};
this.$onChanges = () => {
// Change PO Prefix to empty if the default value isn't replaced by a value set in the template shortcode.
if (this.poPrefix === 'PO_PREFIX') {
this.poPrefix = '';
}
};
const isCostCenterRequired = () => {
return (
$cookies.get('vf.user.cost_center_is_required') === 'true' || false
);
};
this.getCheckout = () => {
vm.isLoading = true;
Checkout.checkout()
.then((response: any) => {
if (!response.data.errors.length) {
vm.extraFields = this.getExtraFields(
response.data.custom_fields
);
vm.acceptedPaymentTypes = getAcceptedPaymentTypes(
response.data.accepted_payment_types
);
vm.customFields = response.data.custom_fields;
vm.hasAdditionalInfo = hasAdditionalInfo();
vm.order = response.data.order;
vm.shippingMethods = response.data.shipping_methods;
vm.hasLockedBilling = response.data.lock_billing;
vm.hasLockedShipping = response.data.lock_shipping;
}
})
.finally(() => {
vm.isLoading = false;
});
};
/**
* @name getAcceptedPaymentTypes
* @param {Object} data Data returned from checkout, with 1 or 0 for flags.
* @return {Object} Keyed-array object with Booleans.
* @memberof Components.CheckoutController
*/
function getAcceptedPaymentTypes(data) {
const types = {};
Object.entries(data).forEach((element) => {
const [key, value] = element;
if (value === true || value === 1) {
types[key] = true;
}
});
return types;
}
/**
* @param {any} customFields Custom fields
* @return {Object} Additional and custom fields
*/
this.getExtraFields = (customFields) => {
const extraFields: {
attention?: ExtraField;
organization?: ExtraField;
cost_center_code?: ExtraField;
issuing_office?: ExtraField;
notes?: ExtraField;
rr_po_num?: ExtraField;
} = {};
const {
general: { checkout: additionalFields },
} = localized.settings;
const enabledAdditionalFields = Object.entries(additionalFields).filter(
(element) => element[1]
);
// Add Additional Fields from Settings to extra fields
const checkoutSettings = localized.settings.general.checkout;
enabledAdditionalFields.forEach((field) => {
const [key] = field;
switch (key) {
case 'attention_option':
extraFields.attention = new ExtraField(
'Attention',
checkoutSettings.attention_option_required
);
break;
case 'company_name_option':
extraFields.organization = new ExtraField(
'Company/Organization',
checkoutSettings.company_name_option_required,
User.company,
'organization'
);
break;
case 'cost_center_option':
extraFields.cost_center_code = new ExtraField(
'Cost Center Code',
checkoutSettings.cost_center_option_required ||
isCostCenterRequired()
);
break;
case 'issuing_office_option':
extraFields.issuing_office = new ExtraField(
'Issuing Office',
checkoutSettings.issuing_office_option_required
);
break;
case 'notes_option':
extraFields.notes = new ExtraField(
'Notes',
checkoutSettings.notes_option_required
);
break;
case 'purchase_order_option':
extraFields.rr_po_num = new ExtraField(
'Purchase Order',
checkoutSettings.purchase_order_option_required,
this.poPrefix
);
break;
}
});
// Add Custom Checkout Fields from Customer Account data to extra fields
Object.entries(customFields).forEach((field) => {
const [key, details]: [key: string, details: any] = field;
extraFields[key] = new ExtraField(details.name, details.required);
if (Array.isArray(details.value)) {
// If multiple preset values
if (details.value.length > 1) {
extraFields[key].options = details.value;
extraFields[key].value = details.value[0];
}
// If one preset value
if (details.value.length === 1 && details.value[0]) {
extraFields[key].value = details.value[0];
extraFields[key].isReadonly = true;
}
} else {
// If value isn't an array, treat like it's one preset value.
extraFields[key].value = details.value;
extraFields[key].isReadonly = true;
}
});
// Remove any fields being replaced.
const replacementFields = Object.entries(customFields).filter(
(field) => field[1].replace_field
);
replacementFields.forEach((field) => {
const key = field[1].replace_field;
if (extraFields[key]) {
delete extraFields[key];
}
});
return extraFields;
};
/**
* @return {boolean} Returns true if any extra fields are enabled in Settings, or any custom fields are enabled for this customer.
*/
function hasAdditionalInfo() {
const {
general: { checkout: extraFields },
} = localized.settings;
return (
Object.values(extraFields).some((element) => element === true) ||
Object.keys(vm.customFields).length > 0
);
}
function setAddresses(): void {
if (!User.isGuest && User.name) {
const userName = User.name.split(' ');
const firstName = userName.shift();
const lastName = userName.join(' ');
vm.billingAddress = {
first_name: firstName,
last_name: lastName,
email: User.email,
};
vm.shippingAddress = {
first_name: firstName,
last_name: lastName,
email: User.email,
};
}
}
this.showTab = (tab: string) => {
const selector = `#checkout-${tab}-tab`;
const el = jQuery(selector);
el.tab('show');
window.scrollTo(0, 0);
};
}