Files
PetitTetonMeteor/imports/ui/Pricing.js

161 lines
6.4 KiB
JavaScript

import './Pricing.html';
/**
* Notes:
* The Product object has a prices field which is an object whose fields names are Measure ID's. Each field value (for each Measure ID) is an object that has a 'price', 'effectiveDate', and 'previousPrice'.
* The effectiveDate field stores the date as a number in the format YYYYMMDD. Converting this number into a local date is done with moment(sale.date.toString(), "YYYYMMDD").toDate(), and converting it to a number from a date can be accomplished with ~~(moment(date).format("YYYYMMDD")), where the ~~ is a bitwise not and converts a string to a number quickly and reliably.
* Because the structure of the Product object is so complicated, the normal checking that is done by the framework cannot be used.
*/
let QUERY_LIMIT = 20;
let PREFIX = "Pricing.";
Meteor.subscribe("products");
let measuresSubscription = Meteor.subscribe("measures");
Tracker.autorun(function() {
let ready = measuresSubscription.ready();
if(ready) {
console.log("setting selected measure session var");
let firstMeasure = Meteor.collections.Measures.findOne({}, {sort: {order: 1}, fields: {_id: 1}});
Session.set(PREFIX + "selectedMeasure", firstMeasure._id);
}
});
Template.Pricing.onCreated(function() {
});
Template.Pricing.onRendered(function() {
this.$('input[name="date"]').val(new Date().toDateInputValue());
// this>$('select[name="measures"]').val()
});
Template.Pricing.helpers({
measures: function() {
let measures = Meteor.collections.Measures.find({}, {sort: {order: 1}}).fetch();
for(let i = 0; i < measures; i++) {
if(Meteor.collections.Products.find({measures: {$all: [measures[i]._id]}}, {sort: {name: 1}}).count() == 0)
measures.splice(i, 1); //Remove the measure from the list.
}
return measures;
},
product: function() {
let skipCount = Session.get(PREFIX + 'skipCount') || 0;
let measureId = Session.get(PREFIX + "selectedMeasure");
let dbQuery = {measures: {$all: [measureId]}, $or: [{hidden: false}, {hidden: {$exists:false}}]};
Session.set(PREFIX + 'productCount', Meteor.collections.Products.find(dbQuery).count()); //Always get a full count.
return Meteor.collections.Products.find(dbQuery, {limit: QUERY_LIMIT, skip: skipCount, sort: {name: 1}});
},
disablePrev: function() {
return (Session.get(PREFIX + 'skipCount') || 0) == 0;
},
disableNext: function() {
return Session.get(PREFIX + 'productCount') - (Session.get(PREFIX + 'skipCount') || 0) - QUERY_LIMIT <= 0;
}
});
Template.Pricing.events({
'change select[name="measures"]': function(event, template) {
Session.get(PREFIX + 'skipCount', 0);
Session.set(PREFIX + "selectedMeasure", $(event.target).val());
},
'click .applyButton': function(event, template) {
let measureId = template.$('select[name="measures"]').val();
let $selectedRows = template.$('tr.selected');
let price = Number(template.$('input[name="price"]').val());
let setPrevious = template.$('input[name="setPrevious"]').prop('checked');
let date = template.$('input[name="date"]').val();
let productIds = [];
for(let i = 0; i < $selectedRows.length; i++) {
let product = $($selectedRows[i]).data('product');
productIds.push(product._id);
}
if(!price) {
Meteor.call("clearProductPrice", productIds, measureId)
}
else {
date = ~~(moment(date ? date : new Date().toDateInputValue(), "YYYY-MM-DD").format("YYYYMMDD")); // The ~~ is a bitwise not which converts the string into a number in the format of YYYYMMDD for storage in the database; to avoid timezone issues.
setPrevious = setPrevious == true || setPrevious == 'on' || setPrevious == "true" || setPrevious == "yes";
if(setPrevious == true && !date) {
sAlert.error("Unexpected input.");
}
if(!price || isNaN(price) || price < 0) {
sAlert.error("Unexpected input.");
}
Meteor.call("setProductPrice", productIds, measureId, price, setPrevious, date);
}
},
'click .resetButton': function(event, template) {
template.$('input.price').val(0);
template.$('input.date').val(new Date().toDateInputValue());
template.$('input[name="setPrevious"]').removeProp('checked');
},
'click .prevProducts': function(event, template) {
if(!$(event.target).hasClass('disabled'))
Session.set(PREFIX + 'skipCount', Math.max(0, (Session.get(PREFIX + 'skipCount') || 0) - QUERY_LIMIT));
},
'click .nextProducts': function(event, template) {
if(!$(event.target).hasClass('disabled'))
Session.set(PREFIX + 'skipCount', (Session.get(PREFIX + 'skipCount') || 0) + QUERY_LIMIT);
}
});
Template.PricingForProduct.onRendered(function() {
this.$('tr').data("product", this.data);
});
Template.PricingForProduct.helpers({
currentPrice: function() {
let measureId = Session.get(PREFIX + "selectedMeasure");
let price = this.prices && measureId && this.prices[measureId] && this.prices[measureId].price ? this.prices[measureId].price : undefined;
return price ? price.toLocaleString("en-US", {style: 'currency', currency: 'USD', minimumFractionDigits: 2}) : "-";
},
previousPrice: function() {
let measureId = Session.get(PREFIX + "selectedMeasure");
let price = this.prices && measureId && this.prices[measureId] && this.prices[measureId].previousPrice ? this.prices[measureId].previousPrice : undefined;
return price ? price.toLocaleString("en-US", {style: 'currency', currency: 'USD', minimumFractionDigits: 2}) : "-";
},
priceChangeDate: function() {
let measureId = Session.get(PREFIX + "selectedMeasure");
return this.prices && measureId && this.prices[measureId] && this.prices[measureId].effectiveDate ? moment(this.prices[measureId].effectiveDate.toString(), "YYYYMMDD").format("MM/DD/YYYY (w)") : "-";
},
rowClass: function() {
return this.deactivated ? "deactivated" : "";
}
});
Template.PricingForProduct.events({
'click tr': function(event, template) {
let $row = template.$(event.target).closest("tr");
let parentTemplate = template.parentTemplate(1);
if(event.shiftKey) {
let $lastRow = parentTemplate.$lastClickedRow;
let $range = ($row.index() > $lastRow.index() ? $lastRow.nextUntil($row) : $row.nextUntil($lastRow)).add($row);
if(event.ctrlKey) {
$range.toggleClass("selected");
}
else {
$range.addClass("selected");
}
}
else if(event.ctrlKey) {
$row.toggleClass("selected");
}
else {
$row.addClass("selected");
$row.siblings().removeClass('selected');
}
//Store the last row clicked on in a non-reactive variable attached to the parent template.
parentTemplate.$lastClickedRow = $row;
}
});