Mango.Nop.Plugins/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Views/Order/FruitBankOrderList.cshtml

643 lines
33 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@model Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models.Order.OrderSearchModelExtended
@using FruitBank.Common.Interfaces
@using Nop.Services.Stores
@using Nop.Web.Areas.Admin.Components
@using Nop.Web.Areas.Admin.Models.Orders
@using Nop.Web.Framework.Infrastructure
@inject IStoreService storeService
@{
// Layout = "~/Areas/Admin/Views/Shared/_LayoutAdmin.cshtml";
ViewBag.PageTitle = "FruitBank Rendelések";
NopHtml.SetActiveMenuItemSystemName("Orders");
}
@* ── Action buttons ─────────────────────────────────────────────── *@
<form id="fb-header-form" asp-controller="Order" asp-action="List" method="post">
<div class="content-header clearfix">
<h1 class="float-left">Rendelések</h1>
<div class="float-right">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#create-order-window">
<i class="fas fa-plus"></i> @T("Admin.Common.AddNew")
</button>
<div class="btn-group">
<button type="button" class="btn btn-success"><i class="fas fa-download"></i> @T("Admin.Common.Export")</button>
<button type="button" class="btn btn-success dropdown-toggle dropdown-icon" data-toggle="dropdown"><span class="sr-only">&nbsp;</span></button>
<ul class="dropdown-menu" role="menu">
<li class="dropdown-item"><button asp-action="ExportXml" type="submit" name="exportxml-all"><i class="far fa-file-code"></i> @T("Admin.Common.ExportToXml.All")</button></li>
<li class="dropdown-item"><button type="button" id="exportxml-selected"><i class="far fa-file-code"></i> @T("Admin.Common.ExportToXml.Selected")</button></li>
<li class="dropdown-divider"></li>
<li class="dropdown-item"><button asp-action="ExportExcel" type="submit" name="exportexcel-all"><i class="far fa-file-excel"></i> @T("Admin.Common.ExportToExcel.All")</button></li>
<li class="dropdown-item"><button type="button" id="exportexcel-selected"><i class="far fa-file-excel"></i> @T("Admin.Common.ExportToExcel.Selected")</button></li>
</ul>
</div>
<div class="btn-group">
<button type="button" class="btn btn-info"><i class="far fa-file-pdf"></i> @T("Admin.Orders.PdfInvoices")</button>
<button type="button" class="btn btn-info dropdown-toggle dropdown-icon" data-toggle="dropdown"><span class="sr-only">&nbsp;</span></button>
<ul class="dropdown-menu" role="menu">
<li class="dropdown-item"><button asp-action="PdfInvoice" type="submit" name="pdf-invoice-all">@T("Admin.Orders.PdfInvoices.All")</button></li>
<li class="dropdown-item"><button type="button" id="pdf-invoice-selected">@T("Admin.Orders.PdfInvoices.Selected")</button></li>
</ul>
</div>
</div>
</div>
</form>
<section class="content">
<div class="container-fluid">
@* ── Filter Panel ─────────────────────────────────────────────── *@
<div class="card card-default card-search mb-2">
<div class="card-body py-2">
<div class="row align-items-end">
@* Date from *@
<div class="col-md-2">
<div class="form-group mb-1">
<nop-label asp-for="StartDate" />
<nop-editor asp-for="StartDate" />
</div>
</div>
@* Date to *@
<div class="col-md-2">
<div class="form-group mb-1">
<nop-label asp-for="EndDate" />
<nop-editor asp-for="EndDate" />
</div>
</div>
@* Partner autocomplete → stores customer ID in hidden *@
<div class="col-md-4">
<div class="form-group mb-1">
<label class="col-form-label">Partner</label>
<div class="input-group">
<input type="text" id="fb-company-display" autocomplete="off" class="form-control" placeholder="Cég neve..." />
<div class="input-group-append">
<button type="button" id="fb-company-clear" class="btn btn-outline-secondary" style="display:none">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<input asp-for="BillingCompany" type="hidden" id="BillingCompany" />
</div>
</div>
@* Go to order by number *@
<div class="col-md-3">
<div class="form-group mb-1">
<nop-label asp-for="GoDirectlyToCustomOrderNumber" />
<div class="input-group">
<nop-editor asp-for="GoDirectlyToCustomOrderNumber" />
<div class="input-group-append">
<button type="button" id="go-to-order-by-number" class="btn btn-info">
@T("Admin.Common.Go")
</button>
</div>
</div>
</div>
</div>
@* Search button *@
<div class="col-md-1">
<div class="form-group mb-1">
<label class="col-form-label">&nbsp;</label>
<button type="button" id="fb-search-btn" class="btn btn-primary btn-block">
<i class="fas fa-search"></i>
</button>
</div>
</div>
</div>
</div>
</div>
@* ── Grid ─────────────────────────────────────────────────────── *@
<div class="card card-default">
<div class="card-body p-0">
@* Anti-forgery token for AJAX POSTs *@
@Html.AntiForgeryToken()
<table id="fb-orders-grid" class="table table-bordered table-hover m-0 table-responsive" style="width:100%">
<thead>
<tr>
<th><input type="checkbox" id="fb-check-all" title="Összes kijelölése"></th>
<th>Rendelés #</th>
<th>Partner</th>
<th>InnVoice</th>
<th>Súly</th>
<th>Mérendő</th>
<th>Mérés</th>
<th title="Kattintásra szerkeszthető">Átvétel <small class="text-muted">✏️</small></th>
<th>Státusz</th>
<th>Fizetés</th>
<th>Szállítás</th>
<th>Létrehozva</th>
<th>Összeg</th>
<th></th>
</tr>
</thead>
</table>
</div>
<div id="fb-totals-row" class="card-footer py-2" style="display:none">
<div id="fb-totals-content" class="small text-muted"></div>
</div>
</div>
</div>
</section>
@* ── Export selected XML ──────────────────────────────────────── *@
<form asp-controller="Order" asp-action="ExportXmlSelected" method="post" id="export-xml-selected-form">
<input type="hidden" id="export-xml-ids" name="selectedIds" value="" />
</form>
@* ── Export selected Excel ────────────────────────────────────── *@
<form asp-controller="Order" asp-action="ExportExcelSelected" method="post" id="export-excel-selected-form">
<input type="hidden" id="export-excel-ids" name="selectedIds" value="" />
</form>
@* ── PDF selected ───────────────────────────────────────────────── *@
<form asp-controller="Order" asp-action="PdfInvoiceSelected" method="post" id="pdf-invoice-selected-form">
<input type="hidden" id="pdf-invoice-ids" name="selectedIds" value="" />
</form>
@* ── Create Order Modal ─────────────────────────────────────────── *@
<div id="create-order-window" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">@T("Admin.Orders.AddNew")</h4>
<button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
</div>
<form asp-controller="CustomOrder" asp-action="Create" method="post" id="create-order-form">
<div class="form-horizontal">
<div class="modal-body">
<div class="form-group row">
<div class="col-md-3"><label class="col-form-label">@T("Admin.Orders.Fields.Customer")</label></div>
<div class="col-md-9">
<input type="text" id="create-order-customer-search" autocomplete="off" class="form-control" placeholder="Ügyfél neve vagy email..." />
<span id="create-order-customer-name" class="mt-1 d-block"></span>
<input type="hidden" id="create-order-customer-id" name="customerId" />
<span class="field-validation-error" id="create-order-customer-error" style="display:none">Kérjük válasszon ügyfelet</span>
</div>
</div>
<div class="form-group row" id="create-product-search-section" style="display:none">
<div class="col-md-3"><label class="col-form-label">@T("Admin.Orders.Fields.Product")</label></div>
<div class="col-md-9">
<input type="text" id="create-order-product-search" autocomplete="off" class="form-control" placeholder="Termék neve vagy SKU..." />
</div>
</div>
<div id="create-selected-products-section" style="display:none">
<table class="table table-sm table-bordered" id="create-products-table">
<thead><tr><th>Termék</th><th style="width:100px">Menny.</th><th style="width:120px">Egységár</th><th style="width:40px"></th></tr></thead>
<tbody id="create-products-body"></tbody>
</table>
</div>
<input type="hidden" id="create-order-products-json" name="orderProductsJson" />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">@T("Admin.Common.Cancel")</button>
<button type="submit" class="btn btn-primary">@T("Admin.Common.Create")</button>
</div>
</div>
</form>
</div>
</div>
</div>
<style>
/* ── Column filter row ──────────────────────────────────────── */
#fb-orders-grid thead tr.fb-filter-row th {
padding: 3px 4px;
background-color: #f4f6f9;
border-bottom: 2px solid #dee2e6;
}
#fb-orders-grid thead tr.fb-filter-row input,
#fb-orders-grid thead tr.fb-filter-row select {
width: 100%;
height: 26px;
padding: 1px 4px;
font-size: 11px;
border: 1px solid #ced4da;
border-radius: 3px;
background: #fff;
}
#fb-orders-grid thead tr.fb-filter-row input:focus,
#fb-orders-grid thead tr.fb-filter-row select:focus {
outline: none;
border-color: #80bdff;
box-shadow: 0 0 0 2px rgba(0,123,255,.15);
}
/* ── Editable date cell ────────────────────────────────────── */
#fb-orders-grid tbody td.fb-editable-date {
cursor: pointer;
}
#fb-orders-grid tbody td.fb-editable-date:hover {
background-color: #fff8e1;
}
#fb-orders-grid tbody td.fb-editable-date input[type="date"] {
width: 120px;
font-size: 12px;
padding: 1px 4px;
border: 1px solid #80bdff;
border-radius: 3px;
}
/* ── Stripe rows ───────────────────────────────────────────── */
#fb-orders-grid tbody tr:nth-child(even) {
background-color: #f9f9f9;
}
#fb-orders-grid tbody tr:hover {
background-color: #eaf2ff;
}
/* ── Processing overlay ────────────────────────────────────── */
#fb-orders-grid_processing {
background: rgba(255,255,255,0.85);
border: 1px solid #dee2e6;
border-radius: 4px;
padding: 8px 16px;
font-size: 13px;
}
/* autocomplete z-index fix in modals */
.ui-autocomplete { z-index: 1060 !important; }
</style>
<script>
$(function () {
/* ── Helpers ─────────────────────────────────────────────────── */
var _token = $('input[name="__RequestVerificationToken"]').val();
function antiForgery(obj) {
obj['__RequestVerificationToken'] = _token;
return obj;
}
var selectedIds = [];
function getSelectedIds() {
selectedIds = [];
$('#fb-orders-grid tbody .fb-row-check:checked').each(function () {
selectedIds.push($(this).val());
});
return selectedIds;
}
/* ── Column renderers ────────────────────────────────────────── */
function renderInnvoice(data) {
return data
? '<span class="badge badge-success">Igen</span>'
: '<span class="badge badge-secondary">Nem</span>';
}
function renderWeightValid(data) {
return data
? '<span class="badge badge-success">OK</span>'
: '<span class="badge badge-danger font-weight-bold">!</span>';
}
function renderMeasurable(data) {
return data
? '<span class="badge badge-info">Igen</span>'
: '<span class="badge badge-light text-secondary">Nem</span>';
}
function renderMeasuringStatus(val, row) {
var map = { 10: 'warning', 20: 'primary', 30: 'success', 40: 'danger' };
var cls = map[val] || 'secondary';
var label = row.MeasuringStatusString || String(val);
return '<span class="badge badge-' + cls + '">' + label + '</span>';
}
function renderDateOfReceipt(data) {
if (!data) return '<span class="text-muted">—</span>';
var d = new Date(data);
var dateStr = d.toLocaleDateString('hu-HU');
var timeStr = d.toLocaleTimeString('hu-HU', { hour: '2-digit', minute: '2-digit' });
return '<span>' + dateStr + ' ' + timeStr + '</span>';
}
function renderOrderStatus(statusId, row) {
var map = { 10: 'warning', 20: 'primary', 30: 'success', 40: 'danger' };
var cls = map[statusId] || 'secondary';
var label = row.OrderStatus || String(statusId);
return '<span class="badge badge-' + cls + '">' + label + '</span>';
}
/* ── DataTables ──────────────────────────────────────────────── */
var table = $('#fb-orders-grid').DataTable({
serverSide : true,
processing : true,
orderCellsTop: true,
stateSave : false,
pageLength : 50,
lengthMenu : [[20, 50, 100, 200, 500], [20, 50, 100, 200, 500]],
order : [[0, 'desc']],
language : {
processing : 'Betöltés...',
search : 'Keresés:',
lengthMenu : '_MENU_ sor/oldal',
info : '_START_ _END_ / _TOTAL_ rendelés',
infoEmpty : '0 rendelés',
infoFiltered : '(szűrve _MAX_-ból)',
paginate : { first: '««', previous: '«', next: '»', last: '»»' },
emptyTable : 'Nincs találat',
zeroRecords : 'Nincs találat a szűrési feltételekre'
},
ajax: {
url : '@Url.Action("FruitBankOrderList", "CustomOrder")',
type: 'POST',
data: function (d) {
d.StartDate = $('#@Html.IdFor(m => m.StartDate)').val();
d.EndDate = $('#@Html.IdFor(m => m.EndDate)').val();
d.BillingCompany = $('#BillingCompany').val();
addAntiForgeryToken(d);
},
error: function (xhr) {
console.error('FruitBankOrderList AJAX error:', xhr.status, xhr.responseText);
}
},
columns: [
/* 0 */ { data: 'Id', name: 'Id', orderable: false, searchable: false, width: '32px',
className: 'text-center',
render: function (d) { return '<input type="checkbox" class="fb-row-check" value="' + d + '">'; } },
/* 1 */ { data: 'CustomOrderNumber', name: 'CustomOrderNumber', width: '95px' },
/* 2 */ { data: 'CustomerCompany', name: 'CustomerCompany' },
/* 3 */ { data: 'InnvoiceTechId', name: 'InnvoiceTechId', orderable: false, width: '75px',
className: 'text-center',
render: function (d) { return renderInnvoice(d); } },
/* 4 */ { data: 'IsAllOrderItemAvgWeightValid', name: 'IsAllOrderItemAvgWeightValid', orderable: false, width: '55px',
className: 'text-center',
render: function (d) { return renderWeightValid(d); } },
/* 5 */ { data: 'IsMeasurable', name: 'IsMeasurable', orderable: false, width: '65px',
className: 'text-center',
render: function (d) { return renderMeasurable(d); } },
/* 6 */ { data: 'MeasuringStatus', name: 'MeasuringStatus', width: '95px',
className: 'text-center',
render: function (d, t, row) { return renderMeasuringStatus(d, row); } },
/* 7 */ { data: 'DateOfReceipt', name: 'DateOfReceipt', width: '110px',
className: 'text-center fb-editable-date',
render: function (d) { return renderDateOfReceipt(d); } },
/* 8 */ { data: 'OrderStatusId', name: 'OrderStatusId', width: '105px',
className: 'text-center',
render: function (d, t, row) { return renderOrderStatus(d, row); } },
/* 9 */ { data: 'PaymentStatus', name: 'PaymentStatus', orderable: false, width: '110px',
render: function (d) { return d || '—'; } },
/* 10 */ { data: 'ShippingStatus', name: 'ShippingStatus', orderable: false, width: '110px',
render: function (d) { return d || '—'; } },
/* 11 */ { data: 'CreatedOn', name: 'CreatedOn', width: '92px',
className: 'text-center',
render: function (d) { return d ? new Date(d).toLocaleDateString('hu-HU') : '—'; } },
/* 12 */ { data: 'OrderTotal', name: 'OrderTotal', orderable: false, width: '105px',
className: 'text-right' },
/* 13 */ { data: 'Id', name: null, orderable: false, searchable: false, width: '42px',
className: 'text-center',
render: function (d) { return '<a href="/Admin/Order/Edit/' + d + '" class="btn btn-default btn-xs" title="Szerkesztés"><i class="fas fa-pencil-alt"></i></a>'; } }
],
/* ── Per-column filter row ─────────────────────────────────── */
initComplete: function () {
var api = this.api();
var $thead = $(this).find('thead');
var $filterRow = $('<tr class="fb-filter-row"></tr>').appendTo($thead);
// Filter definition per column index:
// null = no filter, 'text' = text input, {type:'select', opts:[...]} = dropdown
var defs = [
null, /* 0 checkbox */
'text', /* 1 order # */
'text', /* 2 company */
{ type: 'select', opts: [['', 'Mind'], ['has', '✓ Igen'], ['none', '✗ Nem']] }, /* 3 innvoice */
null, /* 4 weight (no per-column filter) */
{ type: 'select', opts: [['', 'Mind'], ['true', 'Igen'], ['false', 'Nem']] }, /* 5 measurable */
{ type: 'select', opts: [['', 'Mind'], ['0', 'Nincs'], ['10', '…folyamat'], ['20', 'Mérésre'], ['30', 'Mérve'], ['40', 'Lezárva']] }, /* 6 measuring */
null, /* 7 date (top-level filter handles this) */
{ type: 'select', opts: [['', 'Mind'], ['10', 'Függőben'], ['20', 'Feldolgozás'], ['30', 'Teljesítve'], ['40', 'Törölve']] }, /* 8 order status */
null, /* 9 payment */
null, /* 10 shipping */
null, /* 11 created */
null, /* 12 total */
null /* 13 button */
];
api.columns().every(function (idx) {
var col = this;
var $th = $('<th></th>').appendTo($filterRow);
var def = defs[idx];
if (!def) return;
if (def === 'text') {
var $inp = $('<input type="text" placeholder="🔍">');
$inp.appendTo($th);
var timer;
$inp.on('input', function () {
clearTimeout(timer);
var v = this.value;
timer = setTimeout(function () { col.search(v).draw(); }, 450);
});
} else if (def.type === 'select') {
var $sel = $('<select></select>');
def.opts.forEach(function (o) {
$sel.append($('<option>').val(o[0]).text(o[1]));
});
$sel.appendTo($th);
$sel.on('change', function () { col.search(this.value).draw(); });
}
});
}
});
/* ── Search / filter triggers ────────────────────────────────── */
$('#fb-search-btn').on('click', function () { table.draw(); });
/* redraw on date change */
$('#@Html.IdFor(m => m.StartDate), #@Html.IdFor(m => m.EndDate)').on('change', function () { table.draw(); });
/* ── Partner (company) autocomplete ──────────────────────────── */
$('#fb-company-display').autocomplete({
delay : 400,
minLength: 2,
source : '@Url.Action("CustomerSearchAutoComplete", "CustomOrder")',
select : function (e, ui) {
$('#BillingCompany').val(ui.item.value);
$('#fb-company-display').val(ui.item.label);
$('#fb-company-clear').show();
table.draw();
return false;
}
});
$('#fb-company-clear').on('click', function () {
$('#BillingCompany').val('');
$('#fb-company-display').val('');
$(this).hide();
table.draw();
});
/* ── Checkbox: select all on current page ────────────────────── */
$('#fb-check-all').on('change', function () {
var checked = this.checked;
$('#fb-orders-grid tbody .fb-row-check').prop('checked', checked);
});
/* ── Inline editing: DateOfReceipt ───────────────────────────── */
$(document).on('click', '#fb-orders-grid tbody td.fb-editable-date', function (e) {
var $td = $(this);
if ($td.find('input').length) return; // already in edit mode
var $row = $td.closest('tr');
var rowData = table.row($row).data();
if (!rowData) return;
// Build a datetime-local string (YYYY-MM-DDTHH:mm) for the input value
function toDatetimeLocal(iso) {
if (!iso) return '';
var d = new Date(iso);
if (isNaN(d)) return '';
var pad = function(n) { return String(n).padStart(2, '0'); };
return d.getFullYear() + '-' + pad(d.getMonth()+1) + '-' + pad(d.getDate()) +
'T' + pad(d.getHours()) + ':' + pad(d.getMinutes());
}
var currentIso = rowData.DateOfReceipt || null;
// Default to now if no date set yet
var inputVal = currentIso ? toDatetimeLocal(currentIso) : toDatetimeLocal(new Date().toISOString());
var orderId = rowData.Id;
var savedHtml = $td.html();
var $inp = $('<input type="datetime-local">').val(inputVal);
$td.html('').append($inp);
$inp.focus();
function restore() { $td.html(savedHtml); }
function persist() {
var newVal = $inp.val(); // format: YYYY-MM-DDTHH:mm
// Compare against original ISO; skip save only if identical
var newIso = newVal ? new Date(newVal).toISOString() : null;
var oldIso = currentIso ? new Date(currentIso).toISOString() : null;
if (newIso === oldIso) { restore(); return; }
$.ajax({
url : '@Url.Action("UpdateOrderField", "CustomOrder")',
type : 'POST',
data : antiForgery({ orderId: orderId, field: 'DateOfReceipt', value: newVal }),
success: function (res) {
if (res.success) {
rowData.DateOfReceipt = newVal || null;
table.row($row).data(rowData).invalidate();
/* re-render only the date cell without full redraw */
$td.html(renderDateOfReceipt(newVal));
} else {
restore();
alert('Mentési hiba: ' + (res.error || 'Ismeretlen hiba'));
}
},
error: function () { restore(); }
});
}
$inp.on('blur', function () { persist(); });
$inp.on('keydown', function (e) {
if (e.key === 'Enter') { $inp.off('blur'); persist(); }
if (e.key === 'Escape') { $inp.off('blur'); restore(); }
});
});
/* ── Go-to order by number ───────────────────────────────────── */
$('#@Html.IdFor(m => m.GoDirectlyToCustomOrderNumber)').on('keydown', function (e) {
if (e.keyCode === 13) { $('#go-to-order-by-number').trigger('click'); return false; }
});
$('#go-to-order-by-number').on('click', function () {
var num = $('#@Html.IdFor(m => m.GoDirectlyToCustomOrderNumber)').val();
if (num) {
window.location.href = '@Url.Action("GoToOrderId", "CustomOrder")?' +
'@Html.IdFor(m => m.GoDirectlyToCustomOrderNumber)=' + encodeURIComponent(num);
}
});
/* ── Export / PDF selected ───────────────────────────────────── */
function exportSelected(formId, inputId) {
var ids = getSelectedIds().join(',');
if (!ids) { alert('@T("Admin.Orders.NoOrders")'); return; }
$(inputId).val(ids);
$(formId).submit();
}
$('#exportxml-selected').on('click', function (e) { e.preventDefault(); exportSelected('#export-xml-selected-form', '#export-xml-ids'); });
$('#exportexcel-selected').on('click', function (e) { e.preventDefault(); exportSelected('#export-excel-selected-form', '#export-excel-ids'); });
$('#pdf-invoice-selected').on('click', function (e) { e.preventDefault(); exportSelected('#pdf-invoice-selected-form', '#pdf-invoice-ids'); });
/* ── Create order modal ──────────────────────────────────────── */
var createProducts = [];
$('#create-order-customer-search').autocomplete({
delay : 400,
minLength: 2,
source : '@Url.Action("CustomerSearchAutoComplete", "CustomOrder")',
select : function (e, ui) {
$('#create-order-customer-id').val(ui.item.value);
$('#create-order-customer-name').html('<strong>' + ui.item.label + '</strong>');
$('#create-order-customer-search').val('');
$('#create-product-search-section').slideDown();
return false;
}
});
$('#create-order-product-search').autocomplete({
delay : 400,
minLength: 2,
source : '@Url.Action("ProductSearchAutoComplete", "CustomOrder")',
select : function (e, ui) {
addCreateProduct(ui.item);
$('#create-order-product-search').val('');
return false;
}
});
function addCreateProduct(item) {
if (createProducts.find(function (p) { return p.id === item.value; })) return;
createProducts.push({ id: item.value, name: item.label, quantity: 1, price: item.price || 0, maxQuantity: item.availableQuantity || 9999 });
renderCreateProducts();
}
function renderCreateProducts() {
var $body = $('#create-products-body').empty();
if (!createProducts.length) { $('#create-selected-products-section').hide(); return; }
$('#create-selected-products-section').show();
createProducts.forEach(function (p, i) {
var maxAttr = p.maxQuantity < 9999 ? ' max="' + p.maxQuantity + '"' : '';
var maxHint = p.maxQuantity < 9999 ? '<br><small class="text-muted">max: ' + p.maxQuantity + ' db</small>' : '';
$body.append(
'<tr>' +
'<td><strong>' + p.name + '</strong></td>' +
'<td><input type="number" class="form-control form-control-sm" min="1"' + maxAttr + ' value="' + p.quantity + '" data-idx="' + i + '" onchange="window._fbUpdateQty(this)">' + maxHint + '</td>' +
'<td><input type="text" class="form-control form-control-sm" value="' + p.price + '" data-idx="' + i + '" onchange="window._fbUpdatePrice(this)"></td>' +
'<td class="text-center"><button type="button" class="btn btn-danger btn-xs" onclick="window._fbRemoveProduct(' + i + ')"><i class="fas fa-trash"></i></button></td>' +
'</tr>'
);
});
$('#create-order-products-json').val(JSON.stringify(createProducts));
}
window._fbUpdateQty = function (el) {
var idx = +el.dataset.idx, val = +el.value, max = createProducts[idx].maxQuantity || 9999;
if (val > max) { val = max; el.value = max; }
if (val < 1) { val = 1; el.value = 1; }
createProducts[idx].quantity = val;
$('#create-order-products-json').val(JSON.stringify(createProducts));
};
window._fbUpdatePrice = function (el) { createProducts[+el.dataset.idx].price = +el.value; renderCreateProducts(); };
window._fbRemoveProduct = function (i) { createProducts.splice(i, 1); renderCreateProducts(); };
$('#create-order-form').on('submit', function (e) {
if (!$('#create-order-customer-id').val()) {
e.preventDefault();
$('#create-order-customer-error').show();
}
});
$('#create-order-window').on('hidden.bs.modal', function () {
$('#create-order-customer-search, #create-order-customer-id, #create-order-customer-name').val('').html('');
$('#create-order-customer-error').hide();
$('#create-product-search-section').hide();
createProducts = [];
renderCreateProducts();
});
});
</script>