2018-07-08 15:16:24 +02:00
var stockOverviewTable = $ ( '#stock-overview-table' ) . DataTable ( {
2018-07-08 16:54:37 +02:00
'paginate' : false ,
2018-05-12 16:15:28 +02:00
'order' : [ [ 3 , 'asc' ] ] ,
'columnDefs' : [
2019-01-05 16:27:26 +01:00
{ 'orderable' : false , 'targets' : 0 } ,
{ 'visible' : false , 'targets' : 4 } ,
{ 'visible' : false , 'targets' : 5 } ,
{ 'visible' : false , 'targets' : 6 }
2018-05-12 16:15:28 +02:00
] ,
2019-09-20 16:26:50 +02:00
'language' : IsJsonString ( _ _t ( 'datatables_localization' ) ) ? JSON . parse ( _ _t ( 'datatables_localization' ) ) : { } ,
2018-07-14 08:48:14 +02:00
'scrollY' : false ,
2018-07-14 10:17:12 +02:00
'colReorder' : true ,
2018-09-08 08:56:32 +02:00
'stateSave' : true ,
'stateSaveParams' : function ( settings , data )
{
data . search . search = "" ;
2018-09-25 08:50:28 +02:00
data . columns . forEach ( column =>
{
column . search . search = "" ;
} ) ;
2018-09-08 08:56:32 +02:00
}
2018-07-08 15:16:24 +02:00
} ) ;
2019-01-05 14:27:40 +01:00
$ ( '#stock-overview-table tbody' ) . removeClass ( "d-none" ) ;
2019-03-04 17:43:12 +01:00
stockOverviewTable . columns . adjust ( ) . draw ( ) ;
2018-07-08 15:16:24 +02:00
2018-07-08 16:54:37 +02:00
$ ( "#location-filter" ) . on ( "change" , function ( )
2018-07-08 15:16:24 +02:00
{
2018-07-08 16:54:37 +02:00
var value = $ ( this ) . val ( ) ;
if ( value === "all" )
2018-07-08 15:16:24 +02:00
{
2018-07-08 16:54:37 +02:00
value = "" ;
}
2019-01-19 00:37:21 -07:00
2018-07-08 16:54:37 +02:00
stockOverviewTable . column ( 4 ) . search ( value ) . draw ( ) ;
} ) ;
2018-07-08 15:16:24 +02:00
2018-10-06 18:19:31 +02:00
$ ( "#product-group-filter" ) . on ( "change" , function ( )
{
var value = $ ( this ) . val ( ) ;
if ( value === "all" )
{
value = "" ;
}
2019-01-19 00:37:21 -07:00
2018-10-06 18:19:31 +02:00
stockOverviewTable . column ( 6 ) . search ( value ) . draw ( ) ;
} ) ;
2018-09-24 19:13:53 +02:00
$ ( "#status-filter" ) . on ( "change" , function ( )
{
var value = $ ( this ) . val ( ) ;
if ( value === "all" )
{
value = "" ;
}
// Transfer CSS classes of selected element to dropdown element (for background)
$ ( this ) . attr ( "class" , $ ( "#" + $ ( this ) . attr ( "id" ) + " option[value='" + value + "']" ) . attr ( "class" ) + " form-control" ) ;
2019-01-19 00:37:21 -07:00
2018-09-24 19:13:53 +02:00
stockOverviewTable . column ( 5 ) . search ( value ) . draw ( ) ;
} ) ;
$ ( ".status-filter-button" ) . on ( "click" , function ( )
{
var value = $ ( this ) . data ( "status-filter" ) ;
$ ( "#status-filter" ) . val ( value ) ;
$ ( "#status-filter" ) . trigger ( "change" ) ;
} ) ;
2018-07-08 16:54:37 +02:00
$ ( "#search" ) . on ( "keyup" , function ( )
{
var value = $ ( this ) . val ( ) ;
if ( value === "all" )
{
value = "" ;
}
2019-01-19 00:37:21 -07:00
2018-07-08 16:54:37 +02:00
stockOverviewTable . search ( value ) . draw ( ) ;
2017-04-16 23:11:03 +02:00
} ) ;
2018-05-12 16:15:28 +02:00
$ ( document ) . on ( 'click' , '.product-consume-button' , function ( e )
{
2018-09-24 09:30:26 +02:00
e . preventDefault ( ) ;
2018-09-25 16:24:43 +02:00
// Remove the focus from the current button
// to prevent that the tooltip stays until clicked anywhere else
document . activeElement . blur ( ) ;
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . BeginUiBusy ( ) ;
2019-01-19 00:37:21 -07:00
2018-05-12 16:15:28 +02:00
var productId = $ ( e . currentTarget ) . attr ( 'data-product-id' ) ;
2018-05-13 08:42:45 +02:00
var consumeAmount = $ ( e . currentTarget ) . attr ( 'data-consume-amount' ) ;
2019-07-06 18:15:53 +02:00
var wasSpoiled = $ ( e . currentTarget ) . hasClass ( "product-consume-button-spoiled" ) ;
2018-05-12 16:15:28 +02:00
2019-07-06 18:15:53 +02:00
Grocy . Api . Post ( 'stock/products/' + productId + '/consume' , { 'amount' : consumeAmount , 'spoiled' : wasSpoiled } ,
2019-09-20 13:37:53 +02:00
function ( bookingResponse )
2018-05-12 16:15:28 +02:00
{
2019-01-19 14:51:51 +01:00
Grocy . Api . Get ( 'stock/products/' + productId ,
2018-08-07 20:11:08 +02:00
function ( result )
2018-05-13 08:42:45 +02:00
{
2019-09-20 13:37:53 +02:00
var toastMessage = _ _t ( 'Removed %1$s of %2$s from stock' , consumeAmount . toString ( ) + " " + _ _n ( consumeAmount , result . quantity _unit _stock . name , result . quantity _unit _stock . name _plural ) , result . product . name ) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBooking(' + bookingResponse . id + ')"><i class="fas fa-undo"></i> ' + _ _t ( "Undo" ) + '</a>' ;
2019-07-06 18:15:53 +02:00
if ( wasSpoiled )
{
toastMessage += " (" + _ _t ( "Spoiled" ) + ")" ;
}
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . EndUiBusy ( ) ;
2019-07-06 18:15:53 +02:00
toastr . success ( toastMessage ) ;
2018-08-07 20:11:08 +02:00
RefreshStatistics ( ) ;
2019-09-20 13:37:53 +02:00
RefreshProductRow ( productId ) ;
2018-08-07 20:11:08 +02:00
} ,
function ( xhr )
{
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . EndUiBusy ( ) ;
2018-08-07 20:11:08 +02:00
console . error ( xhr ) ;
}
) ;
2018-05-12 16:15:28 +02:00
} ,
function ( xhr )
{
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . EndUiBusy ( ) ;
2018-05-12 16:15:28 +02:00
console . error ( xhr ) ;
}
) ;
} ) ;
2018-08-04 14:25:32 +02:00
2018-11-17 19:39:37 +01:00
$ ( document ) . on ( 'click' , '.product-open-button' , function ( e )
{
e . preventDefault ( ) ;
// Remove the focus from the current button
// to prevent that the tooltip stays until clicked anywhere else
document . activeElement . blur ( ) ;
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . BeginUiBusy ( ) ;
2019-01-19 00:37:21 -07:00
2018-11-17 19:39:37 +01:00
var productId = $ ( e . currentTarget ) . attr ( 'data-product-id' ) ;
var productName = $ ( e . currentTarget ) . attr ( 'data-product-name' ) ;
var productQuName = $ ( e . currentTarget ) . attr ( 'data-product-qu-name' ) ;
2018-11-18 13:35:21 +01:00
var button = $ ( e . currentTarget ) ;
2018-11-17 19:39:37 +01:00
2019-01-19 14:51:51 +01:00
Grocy . Api . Post ( 'stock/products/' + productId + '/open' , { 'amount' : 1 } ,
2019-09-20 13:37:53 +02:00
function ( bookingResponse )
2018-11-17 19:39:37 +01:00
{
2019-01-19 14:51:51 +01:00
Grocy . Api . Get ( 'stock/products/' + productId ,
2018-11-17 19:39:37 +01:00
function ( result )
{
2018-11-18 13:35:21 +01:00
if ( result . stock _amount == result . stock _amount _opened )
{
button . addClass ( "disabled" ) ;
}
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . EndUiBusy ( ) ;
2019-09-20 13:37:53 +02:00
toastr . success ( _ _t ( 'Marked %1$s of %2$s as opened' , 1 + " " + productQuName , productName ) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBooking(' + bookingResponse . id + ')"><i class="fas fa-undo"></i> ' + _ _t ( "Undo" ) + '</a>' ) ;
2018-11-17 19:39:37 +01:00
RefreshStatistics ( ) ;
2019-09-20 13:37:53 +02:00
RefreshProductRow ( productId ) ;
2018-11-17 19:39:37 +01:00
} ,
function ( xhr )
{
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . EndUiBusy ( ) ;
2018-11-17 19:39:37 +01:00
console . error ( xhr ) ;
}
) ;
} ,
function ( xhr )
{
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . EndUiBusy ( ) ;
2018-11-17 19:39:37 +01:00
console . error ( xhr ) ;
}
) ;
} ) ;
2018-10-01 20:20:50 +02:00
$ ( document ) . on ( "click" , ".product-name-cell" , function ( e )
2018-09-30 23:22:17 +02:00
{
2018-10-22 19:28:59 +02:00
Grocy . Components . ProductCard . Refresh ( $ ( e . currentTarget ) . attr ( "data-product-id" ) ) ;
$ ( "#stockoverview-productcard-modal" ) . modal ( "show" ) ;
2018-09-30 23:22:17 +02:00
} ) ;
2018-08-04 14:25:32 +02:00
function RefreshStatistics ( )
{
2019-01-19 00:37:21 -07:00
Grocy . Api . Get ( 'stock' ,
2018-08-04 14:25:32 +02:00
function ( result )
{
var amountSum = 0 ;
result . forEach ( element => {
amountSum += parseInt ( element . amount ) ;
} ) ;
2019-05-02 20:20:18 +02:00
$ ( "#info-current-stock" ) . text ( _ _n ( result . length , '%s Product' , '%s Products' ) + ", " + _ _n ( amountSum , '%s Unit' , '%s Units' ) ) ;
2018-08-04 14:25:32 +02:00
} ,
function ( xhr )
{
console . error ( xhr ) ;
}
) ;
var nextXDays = $ ( "#info-expiring-products" ) . data ( "next-x-days" ) ;
2019-01-19 00:37:21 -07:00
Grocy . Api . Get ( 'stock/volatile?expiring_days=' + nextXDays ,
2018-08-04 14:25:32 +02:00
function ( result )
{
2019-05-02 20:20:18 +02:00
$ ( "#info-expiring-products" ) . text ( _ _n ( result . expiring _products . length , '%s product expires' , '%s products expiring' ) + ' ' + _ _n ( nextXDays , 'within the next day' , 'within the next %s days' ) ) ;
$ ( "#info-expired-products" ) . text ( _ _n ( result . expired _products . length , '%s product is already expired' , '%s products are already expired' ) ) ;
$ ( "#info-missing-products" ) . text ( _ _n ( result . missing _products . length , '%s product is below defined min. stock amount' , '%s products are below defined min. stock amount' ) ) ;
2018-08-04 14:25:32 +02:00
} ,
function ( xhr )
{
console . error ( xhr ) ;
}
) ;
}
RefreshStatistics ( ) ;
2019-09-20 13:37:53 +02:00
$ ( document ) . on ( "click" , ".product-purchase-button" , function ( e )
{
e . preventDefault ( ) ;
var productId = $ ( e . currentTarget ) . attr ( "data-product-id" ) ;
bootbox . dialog ( {
message : '<iframe height="650px" class="embed-responsive" src="' + U ( "/purchase?embedded&product=" ) + productId . toString ( ) + '"></iframe>' ,
size : 'large' ,
backdrop : true ,
closeButton : false ,
buttons : {
cancel : {
label : _ _t ( 'Cancel' ) ,
className : 'btn-secondary responsive-button' ,
callback : function ( )
{
bootbox . hideAll ( ) ;
}
}
}
} ) ;
} ) ;
$ ( document ) . on ( "click" , ".product-consume-custom-amount-button" , function ( e )
{
e . preventDefault ( ) ;
var productId = $ ( e . currentTarget ) . attr ( "data-product-id" ) ;
bootbox . dialog ( {
message : '<iframe height="650px" class="embed-responsive" src="' + U ( "/consume?embedded&product=" ) + productId . toString ( ) + '"></iframe>' ,
size : 'large' ,
backdrop : true ,
closeButton : false ,
buttons : {
cancel : {
label : _ _t ( 'Cancel' ) ,
className : 'btn-secondary responsive-button' ,
callback : function ( )
{
bootbox . hideAll ( ) ;
}
}
}
} ) ;
} ) ;
$ ( document ) . on ( "click" , ".product-inventory-button" , function ( e )
{
e . preventDefault ( ) ;
var productId = $ ( e . currentTarget ) . attr ( "data-product-id" ) ;
bootbox . dialog ( {
message : '<iframe height="650px" class="embed-responsive" src="' + U ( "/inventory?embedded&product=" ) + productId . toString ( ) + '"></iframe>' ,
size : 'large' ,
backdrop : true ,
closeButton : false ,
buttons : {
cancel : {
label : _ _t ( 'Cancel' ) ,
className : 'btn-secondary responsive-button' ,
callback : function ( )
{
bootbox . hideAll ( ) ;
}
}
}
} ) ;
} ) ;
$ ( document ) . on ( "click" , ".product-add-to-shopping-list-button" , function ( e )
{
e . preventDefault ( ) ;
var productId = $ ( e . currentTarget ) . attr ( "data-product-id" ) ;
bootbox . dialog ( {
message : '<iframe height="650px" class="embed-responsive" src="' + U ( "/shoppinglistitem/new?embedded&product=" ) + productId . toString ( ) + '"></iframe>' ,
size : 'large' ,
backdrop : true ,
closeButton : false ,
buttons : {
cancel : {
label : _ _t ( 'Cancel' ) ,
className : 'btn-secondary responsive-button' ,
callback : function ( )
{
bootbox . hideAll ( ) ;
}
}
}
} ) ;
} ) ;
function RefreshProductRow ( productId )
{
productId = productId . toString ( ) ;
Grocy . Api . Get ( 'stock/products/' + productId ,
function ( result )
{
var productRow = $ ( '#product-' + productId + '-row' ) ;
var expiringThreshold = moment ( ) . add ( "-" + $ ( "#info-expiring-products" ) . data ( "next-x-days" ) , "days" ) ;
var now = moment ( ) ;
var nextBestBeforeDate = moment ( result . next _best _before _date ) ;
productRow . removeClass ( "table-warning" ) ;
productRow . removeClass ( "table-danger" ) ;
if ( now . isAfter ( nextBestBeforeDate ) )
{
productRow . addClass ( "table-danger" ) ;
}
else if ( nextBestBeforeDate . isAfter ( expiringThreshold ) )
{
productRow . addClass ( "table-warning" ) ;
}
if ( result . stock _amount <= 0 )
{
$ ( '#product-' + productId + '-row' ) . fadeOut ( 500 , function ( )
{
$ ( this ) . tooltip ( "hide" ) ;
$ ( this ) . remove ( ) ;
} ) ;
}
else
{
$ ( '#product-' + productId + '-qu-name' ) . text ( _ _n ( result . stock _amount , result . quantity _unit _stock . name , result . quantity _unit _stock . name _plural ) ) ;
$ ( '#product-' + productId + '-amount' ) . parent ( ) . effect ( 'highlight' , { } , 500 ) ;
$ ( '#product-' + productId + '-amount' ) . fadeOut ( 500 , function ( )
{
$ ( this ) . text ( result . stock _amount ) . fadeIn ( 500 ) ;
} ) ;
$ ( '#product-' + productId + '-consume-all-button' ) . attr ( 'data-consume-amount' , result . stock _amount ) ;
$ ( '#product-' + productId + '-next-best-before-date' ) . parent ( ) . effect ( 'highlight' , { } , 500 ) ;
$ ( '#product-' + productId + '-next-best-before-date' ) . fadeOut ( 500 , function ( )
{
$ ( this ) . text ( result . next _best _before _date ) . fadeIn ( 500 ) ;
} ) ;
$ ( '#product-' + productId + '-next-best-before-date-timeago' ) . attr ( 'datetime' , result . next _best _before _date ) ;
var openedAmount = result . stock _amount _opened || 0 ;
$ ( '#product-' + productId + '-opened-amount' ) . parent ( ) . effect ( 'highlight' , { } , 500 ) ;
$ ( '#product-' + productId + '-opened-amount' ) . fadeOut ( 500 , function ( )
{
if ( openedAmount > 0 )
{
$ ( this ) . text ( _ _t ( '%s opened' , openedAmount ) ) . fadeIn ( 500 ) ;
}
else
{
$ ( this ) . text ( "" ) . fadeIn ( 500 ) ;
}
} ) ;
}
$ ( '#product-' + productId + '-next-best-before-date' ) . parent ( ) . effect ( 'highlight' , { } , 500 ) ;
$ ( '#product-' + productId + '-next-best-before-date' ) . fadeOut ( 500 , function ( )
{
$ ( this ) . text ( result . next _best _before _date ) . fadeIn ( 500 ) ;
} ) ;
$ ( '#product-' + productId + '-next-best-before-date-timeago' ) . attr ( 'datetime' , result . next _best _before _date ) ;
if ( result . stock _amount _opened > 0 )
{
$ ( '#product-' + productId + '-opened-amount' ) . parent ( ) . effect ( 'highlight' , { } , 500 ) ;
$ ( '#product-' + productId + '-opened-amount' ) . fadeOut ( 500 , function ( )
{
$ ( this ) . text ( _ _t ( '%s opened' , result . stock _amount _opened ) ) . fadeIn ( 500 ) ;
} ) ;
}
else
{
$ ( '#product-' + productId + '-opened-amount' ) . text ( "" ) ;
}
// Needs to be delayed because of the animation above the date-text would be wrong if fired immediately...
setTimeout ( function ( )
{
RefreshContextualTimeago ( ) ;
} , 600 ) ;
} ,
function ( xhr )
{
Grocy . FrontendHelpers . EndUiBusy ( ) ;
console . error ( xhr ) ;
}
) ;
}
$ ( window ) . on ( "message" , function ( e )
{
var data = e . originalEvent . data ;
if ( data . Message === "ProductChanged" )
{
RefreshProductRow ( data . Payload ) ;
RefreshStatistics ( ) ;
}
} ) ;