grocy/js/components/productcard.js
2021-06-24 00:09:17 +02:00

258 lines
8.9 KiB
JavaScript

import Chart from 'chart.js';
import { EmptyElementWhenMatches } from '../helpers/extensions'
import { RefreshContextualTimeago } from '../configs/timeago'
class productcard
{
constructor(Grocy, scopeSelector = null)
{
this.Grocy = Grocy;
this.scopeSelector = scopeSelector;
this.scope = scopeSelector != null ? $(scopeSelector) : $(document);
this.$ = scopeSelector != null ? (selector) => this.scope.find(selector) : $;
this.PriceHistoryChart = null;
var self = this;
this.$("#productcard-product-description").on("shown.bs.collapse", function()
{
self.$(".expandable-text")
.find("a[data-toggle='collapse']")
.text(self.Grocy.translate("Show less"));
})
this.$("#productcard-product-description").on("hidden.bs.collapse", function()
{
self.$(".expandable-text")
.find("a[data-toggle='collapse']")
.text(self.Grocy.translate("Show more"));
})
}
Refresh(productId)
{
var self = this;
this.Grocy.Api.Get('stock/products/' + productId,
function(productDetails)
{
var stockAmount = productDetails.stock_amount || '0';
var stockValue = productDetails.stock_value || '0';
var stockAmountOpened = productDetails.stock_amount_opened || '0';
self.$('#productcard-product-name').text(productDetails.product.name);
self.$('#productcard-product-description').html(productDetails.product.description);
self.$('#productcard-product-stock-amount').text(stockAmount);
self.$('#productcard-product-stock-qu-name').text(self.Grocy.translaten(stockAmount, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural));
self.$('#productcard-product-stock-value').text(stockValue + ' ' + self.Grocy.Currency);
self.$('#productcard-product-last-purchased').text((productDetails.last_purchased || '2999-12-31').substring(0, 10));
self.$('#productcard-product-last-purchased-timeago').attr("datetime", productDetails.last_purchased || '2999-12-31');
self.$('#productcard-product-last-used').text((productDetails.last_used || '2999-12-31').substring(0, 10));
self.$('#productcard-product-last-used-timeago').attr("datetime", productDetails.last_used || '2999-12-31');
if (productDetails.location != null)
{
self.$('#productcard-product-location').text(productDetails.location.name);
}
self.$('#productcard-product-spoil-rate').text((parseFloat(productDetails.spoil_rate_percent) / 100).toLocaleString(undefined, { style: "percent" }));
if (productDetails.is_aggregated_amount == 1)
{
self.$('#productcard-product-stock-amount-aggregated').text(productDetails.stock_amount_aggregated);
self.$('#productcard-product-stock-qu-name-aggregated').text(self.Grocy.translaten(productDetails.stock_amount_aggregated, productDetails.quantity_unit_stock.name, productDetails.quantity_unit_stock.name_plural));
if (productDetails.stock_amount_opened_aggregated > 0)
{
self.$('#productcard-product-stock-opened-amount-aggregated').text(self.Grocy.translate('%s opened', productDetails.stock_amount_opened_aggregated));
}
else
{
self.$('#productcard-product-stock-opened-amount-aggregated').text("");
}
self.$("#productcard-aggregated-amounts").removeClass("d-none");
}
else
{
self.$("#productcard-aggregated-amounts").addClass("d-none");
}
if (productDetails.product.description != null && !productDetails.product.description.isEmpty())
{
self.$("#productcard-product-description-wrapper").removeClass("d-none");
}
else
{
self.$("#productcard-product-description-wrapper").addClass("d-none");
}
if (productDetails.average_shelf_life_days == -1)
{
self.$('#productcard-product-average-shelf-life').text(self.Grocy.translate("Unknown"));
}
else if (parseInt(productDetails.average_shelf_life_days) > 73000) // > 200 years aka forever
{
self.$('#productcard-product-average-shelf-life').text(self.Grocy.translate("Unlimited"));
}
else
{
self.$('#productcard-product-average-shelf-life').text(moment.duration(productDetails.average_shelf_life_days, "days").humanize());
}
if (stockAmountOpened > 0)
{
self.$('#productcard-product-stock-opened-amount').text(self.Grocy.translate('%s opened', stockAmountOpened));
}
else
{
self.$('#productcard-product-stock-opened-amount').text("");
}
self.$('#productcard-product-edit-button').attr("href", self.Grocy.FormatUrl("/product/" + productDetails.product.id.toString() + '?' + 'returnto=' + encodeURIComponent(self.Grocy.CurrentUrlRelative)));
self.$('#productcard-product-journal-button').attr("href", self.Grocy.FormatUrl("/stockjournal?embedded&product=" + productDetails.product.id.toString()));
self.$('#productcard-product-stock-button').attr("href", self.Grocy.FormatUrl("/stockentries?embedded&product=" + productDetails.product.id.toString()));
self.$('#productcard-product-stock-button').removeClass("disabled");
self.$('#productcard-product-edit-button').removeClass("disabled");
self.$('#productcard-product-journal-button').removeClass("disabled");
if (productDetails.last_price !== null)
{
self.$('#productcard-product-last-price').text(Number.parseFloat(productDetails.last_price).toLocaleString() + ' ' + self.Grocy.Currency + ' per ' + productDetails.quantity_unit_stock.name);
}
else
{
self.$('#productcard-product-last-price').text(self.Grocy.translate('Unknown'));
}
if (productDetails.avg_price !== null)
{
self.$('#productcard-product-average-price').text(Number.parseFloat(productDetails.avg_price).toLocaleString() + ' ' + self.Grocy.Currency + ' per ' + productDetails.quantity_unit_stock.name);
}
else
{
self.$('#productcard-product-average-price').text(self.Grocy.translate('Unknown'));
}
if (productDetails.product.picture_file_name !== null && !productDetails.product.picture_file_name.isEmpty())
{
self.$("#productcard-product-picture").removeClass("d-none");
self.$("#productcard-product-picture").attr("src", self.Grocy.FormatUrl('/api/files/productpictures/' + btoa(productDetails.product.picture_file_name) + '?force_serve_as=picture&best_fit_width=400'));
}
else
{
self.$("#productcard-product-picture").addClass("d-none");
}
EmptyElementWhenMatches(self.$('#productcard-product-last-purchased-timeago'), self.Grocy.translate('timeago_nan'));
EmptyElementWhenMatches(self.$('#productcard-product-last-used-timeago'), self.Grocy.translate('timeago_nan'));
RefreshContextualTimeago(".productcard");
},
function(xhr)
{
console.error(xhr);
}
);
if (this.Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
{
this.Grocy.Api.Get('stock/products/' + productId + '/price-history',
function(priceHistoryDataPoints)
{
if (priceHistoryDataPoints.length > 0)
{
self.$("#productcard-product-price-history-chart").removeClass("d-none");
self.$("#productcard-no-price-data-hint").addClass("d-none");
self.ReInitPriceHistoryChart();
var datasets = {};
var chart = self.PriceHistoryChart.data;
for (let dataPoint of priceHistoryDataPoints)
{
let key = self.Grocy.translate("Unknown store");
if (dataPoint.shopping_location)
{
key = dataPoint.shopping_location.name
}
if (!datasets[key])
{
datasets[key] = []
}
chart.labels.push(moment(dataPoint.date).toDate());
datasets[key].push(dataPoint.price);
}
for (let key of Object.keys(datasets))
{
chart.datasets.push({
data: datasets[key],
fill: false,
borderColor: "HSL(" + (129 * chart.datasets.length) + ",100%,50%)",
label: key,
});
}
self.PriceHistoryChart.update();
}
else
{
self.$("#productcard-product-price-history-chart").addClass("d-none");
self.$("#productcard-no-price-data-hint").removeClass("d-none");
}
},
function(xhr)
{
console.error(xhr);
}
);
}
}
ReInitPriceHistoryChart()
{
if (this.PriceHistoryChart !== null)
{
this.PriceHistoryChart.destroy();
}
var format = 'YYYY-MM-DD';
this.PriceHistoryChart = new Chart(this.$("#productcard-product-price-history-chart")[0], {
type: "line",
data: {
labels: [ //Date objects
// Will be populated in Grocy.Components.ProductCard.Refresh
],
datasets: [ //Datasets
// Will be populated in Grocy.Components.ProductCard.Refresh
]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
parser: format,
round: 'day',
tooltipFormat: format,
unit: 'day',
unitStepSize: 10,
displayFormats: {
'day': format
}
},
ticks: {
autoSkip: true,
maxRotation: 0
}
}],
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
legend: {
display: true
}
}
});
}
}
export { productcard }