174 lines
6.6 KiB
JavaScript

/**
* Forms Component - Handles form data and validation
*/
const FormsComponent = {
/**
* Initialize forms state
* @returns {Object}
*/
getInitialState() {
return {
form: {
initials: '',
lastname: '',
postcode: '',
houseno: '',
suffix: '',
street: '',
city: '',
email: '',
phone: ''
},
meta: {
mediacode: ''
},
addressError: ''
};
},
/**
* Get forms methods for Alpine.js component
* @returns {Object}
*/
getMethods() {
return {
/**
* Format initials with dots (e.g., "JK" -> "J.K.")
*/
formatInitials() {
let v = this.form.initials.replace(/[^a-z]/gi, '').toUpperCase();
this.form.initials = v.split('').join('.') + (v ? '.' : '');
},
/**
* Capitalize first letter of lastname
*/
formatLastname() {
this.form.lastname = this.form.lastname.charAt(0).toUpperCase() + this.form.lastname.slice(1);
},
/**
* Lookup address by postcode and house number
*/
async lookupAddress() {
this.addressError = '';
if (this.form.postcode.length >= 6 && this.form.houseno) {
try {
const data = await ApiService.lookupPostcode(this.form.postcode, this.form.houseno);
if (data.street) {
this.form.street = data.street.toUpperCase();
this.form.city = data.city.toUpperCase();
} else if (data.error) {
this.addressError = data.error;
} else {
this.addressError = 'Adres niet gevonden';
}
} catch (e) {
this.addressError = 'Fout bij ophalen adres';
}
}
},
/**
* Reset form for new order
*/
resetForm() {
this.form = {
initials: '',
lastname: '',
postcode: '',
houseno: '',
suffix: '',
street: '',
city: '',
email: '',
phone: ''
};
this.addressError = '';
},
/**
* Build order payload from form data
* Includes prices from sales screen to ensure discounts and free items are applied correctly
* @returns {Object}
*/
buildOrderPayload() {
const address = (this.form.street + ' ' + this.form.houseno + ' ' + (this.form.suffix || '')).trim();
return {
mediacode_internal: this.meta.mediacode,
shipping_total: this.shipping,
billing: {
first_name: this.form.initials,
last_name: this.form.lastname,
address_1: address,
city: this.form.city,
postcode: this.form.postcode,
country: 'NL',
email: this.form.email,
phone: this.form.phone
},
shipping: {
first_name: this.form.initials,
last_name: this.form.lastname,
address_1: address,
city: this.form.city,
postcode: this.form.postcode,
country: 'NL',
email: this.form.email,
phone: this.form.phone
},
line_items: this.cart.map(i => {
// Calculate price excluding VAT (21%)
const priceExclVat = (parseFloat(i.price) / 1.21).toFixed(4);
// For free items, use originalPrice if available, otherwise use price
const originalPriceExclVat = i.originalPrice
? (parseFloat(i.originalPrice) / 1.21).toFixed(4)
: priceExclVat;
// Build line item object
const lineItem = {
product_id: i.id,
variation_id: i.variation_id || 0,
quantity: 1,
// Set subtotal and total to override WooCommerce's price calculation
// subtotal = price before line-level discounts (shows original value)
// total = price after line-level discounts (actual charged amount)
subtotal: i.isFree ? originalPriceExclVat : priceExclVat,
total: i.isFree ? '0.0000' : priceExclVat
};
// Add metadata for tracking discounts and free items
if (i.isFree) {
lineItem.meta_data = [
{ key: '_is_free_item', value: 'yes' },
{ key: '_bogo_rule_id', value: String(i.ruleId || '') },
{ key: '_original_price_incl_vat', value: String(i.originalPrice || i.price) }
];
} else if (i.isDiscounted) {
lineItem.meta_data = [
{ key: '_is_discounted_item', value: 'yes' },
{ key: '_original_price_incl_vat', value: String(i.originalPrice || '') },
{ key: '_bogo_rule_id', value: String(i.ruleId || '') }
];
}
return lineItem;
})
};
},
/**
* Validate form before submission
* @returns {boolean}
*/
isFormValid() {
return this.form.email && this.meta.mediacode && this.cart.length > 0;
}
};
}
};