gruene-seele/resources/views/admin/product/edit.blade.php
Kevin Adametz 8b0a598ba6 Warenwirtschaft: Bugfix — Produkt speichern warf MethodNotAllowed (DELETE)
Das Lösch-Formular für gespeicherte Rezeptur-Inhaltsstoffe war in das
Produkt-Formular verschachtelt; Browser verwerfen das innere <form>-Tag,
wodurch _method=DELETE ins Speichern-Formular leakte. Jetzt Button, der
per JS ein eigenes Formular außerhalb erzeugt und abschickt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 08:45:48 +00:00

659 lines
29 KiB
PHP
Executable file
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.

@extends('layouts.layout-2')
@section('content')
@if ($errors->any())
<div class="row">
<div class="col-sm-12">
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
</div>
</div>
@endif
<h4 class="font-weight-bold py-2 mb-2">
{{ __('Create/Edit Produkt') }}
</h4>
{!! Form::open(['action' => route('admin_product_store'), 'class' => 'form-horizontal', 'id'=>'']) !!}
<input type="hidden" name="id" id="id" value="@if($product->id>0){{$product->id}}@else new @endif">
<div class="text-left mt-0 mb-2">
<button type="submit" class="btn btn-submit">{{ __('save') }}</button>&nbsp;
<a href="{{ route('admin_product_show') }}" class="btn btn-default">{{ __('back') }}</a>
</div>
@include('admin.product.form')
<div class="text-left mt-0 mb-2">
<button type="submit" class="btn btn-submit">{{ __('save') }}</button>&nbsp;
<a href="{{ route('admin_product_show') }}" class="btn btn-default">{{ __('back') }}</a>
</div>
{!! Form::close() !!}
@include('admin.product.images')
@include('admin.product.upload_whitelabel')
@endsection
@section('scripts')
@php
$ingredient_catalog_for_js = $ingredient_catalog->keyBy('id')->map(function ($item) {
return [
'id' => $item->id,
'name' => $item->name,
'inci' => $item->inci,
'effect' => $item->effect,
'default_factor' => $item->default_factor,
'quality_name' => $item->materialQuality?->name ?? '',
];
});
$packaging_catalog_for_js = $packaging_catalog->keyBy('id')->map(function ($item) {
return [
'name' => $item->name,
'weight_grams' => $item->weight_grams,
'material_name' => $item->packagingMaterial?->name ?? '',
];
});
$set_product_catalog_for_js = $set_product_catalog->keyBy('id')->map(function ($item) {
return [
'name' => $item->name,
'number' => $item->number,
'weight' => $item->weight ? $item->weight . ' g' : '—',
'price' => $item->getFormattedPrice() !== '' ? $item->getFormattedPrice() . ' €' : '—',
];
});
@endphp
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.2/Sortable.min.js"></script>
<script>
(function ($) {
var catalog = @json($ingredient_catalog_for_js);
var packagingCatalog = @json($packaging_catalog_for_js);
var setCatalog = @json($set_product_catalog_for_js);
function parseDeNumber(val) {
if (val === undefined || val === null || val === '') return NaN;
var s = String(val).replace(/\s/g, '');
// Audit N-6: einzelner Punkt mit 1–2 Nachkommastellen = Dezimaltrenner;
// sonst deutsche Konvention (Punkt = Tausender) — wie serverseitig.
if (!/^-?\d+\.\d{1,2}$/.test(s)) {
s = s.replace(/\./g, '');
}
var n = parseFloat(s.replace(',', '.'));
return isNaN(n) ? NaN : n;
}
function updateEffective($row) {
var g = parseDeNumber($row.find('.pi-gram').val());
var f = parseDeNumber($row.find('.pi-factor').val());
var $out = $row.find('.pi-effective');
if (!isNaN(g) && !isNaN(f)) {
var eff = g * f;
$out.text(eff.toLocaleString('de-DE', { minimumFractionDigits: 6, maximumFractionDigits: 6 }));
} else {
$out.text('—');
}
}
function updateRecipeTotal() {
var total = 0;
var hasValue = false;
$('#ingredient-sortable-rows tr').each(function () {
var v = parseDeNumber($(this).find('.pi-gram').val());
if (!isNaN(v)) { total += v; hasValue = true; }
});
var $cell = $('#recipe-total-percent');
if (!hasValue) {
$cell.text('—').removeClass('text-danger text-success');
return;
}
var formatted = total.toLocaleString('de-DE', { minimumFractionDigits: 6, maximumFractionDigits: 6 }) + ' %';
$cell.text(formatted);
var diff = Math.abs(total - 100);
if (diff < 0.000001) {
$cell.removeClass('text-danger').addClass('text-success');
$cell.attr('title', '');
} else {
$cell.removeClass('text-success').addClass('text-danger');
$cell.attr('title', 'Die Gesamtrezeptur ergibt nicht 100 %!');
}
}
function refreshAllEffectives() {
$('#ingredient-sortable-rows tr').each(function () { updateEffective($(this)); });
updateRecipeTotal();
}
$(document).ready(function () {
var $tbody = document.getElementById('ingredient-sortable-rows');
if ($tbody && typeof Sortable !== 'undefined') {
new Sortable($tbody, {
handle: '.ingredient-drag-handle',
animation: 150,
});
}
function appendIngredientRow(id) {
id = String(id);
var ing = catalog[id];
if (!ing) return;
var factor = ing.default_factor != null ? String(ing.default_factor).replace('.', ',') : '1,10';
var row = $('<tr data-ingredient-id="' + id + '">' +
'<td class="text-muted align-middle ingredient-drag-handle" style="cursor:grab">&#9776;</td>' +
'<td class="align-middle"></td><td class="align-middle small text-muted"></td><td class="align-middle"></td>' +
'<td><input type="hidden" name="pi_ingredient_id[]" value="' + id + '">' +
'<input type="text" name="pi_gram[]" class="form-control form-control-sm pi-gram" value="" autocomplete="off" step="0.000001"></td>' +
'<td><input type="text" name="pi_factor[]" class="form-control form-control-sm pi-factor" value="' + factor + '" autocomplete="off"></td>' +
'<td class="align-middle pi-effective text-right small text-muted">—</td>' +
'<td class="align-middle"><a class="text-danger ingredient-row-remove" href="#" title="Entfernen"><i class="far fa-trash-alt"></i></a></td></tr>');
row.find('td').eq(1).text(ing.name || '');
row.find('td').eq(2).text(ing.quality_name || '—');
row.find('td').eq(3).text(ing.inci || '');
$('#ingredient-sortable-rows').append(row);
updateEffective(row);
updateRecipeTotal();
}
function syncIngredientModalRows() {
var usedIds = {};
$('#ingredient-sortable-rows tr').each(function () {
var id = $(this).data('ingredient-id');
if (id) usedIds[String(id)] = true;
});
$('#modal-ingredients-pick .ingredient-modal-row').each(function () {
var id = String($(this).data('ingredient-id'));
var inUse = !!usedIds[id];
var $cb = $(this).find('.js-ingredient-modal-cb');
$cb.prop('disabled', inUse);
$cb.attr('title', inUse ? '{{ __('Bereits im Produkt') }}' : '');
if (inUse) {
$cb.prop('checked', false);
}
$(this).toggleClass('text-muted', inUse);
$(this).css('opacity', inUse ? 0.65 : 1);
$(this).find('.js-ing-modal-name').toggleClass('text-muted', inUse);
$(this).find('.js-ing-modal-inci').toggleClass('text-muted', inUse);
});
}
function filterIngredientModalRows() {
var q = $('#ingredient-modal-search').val().trim().toLowerCase();
var visible = 0;
$('#ingredient-modal-tbody .ingredient-modal-row').each(function () {
var hay = $(this).attr('data-ingredient-search') || '';
var match = !q || hay.indexOf(q) !== -1;
$(this).toggle(match);
if (match) {
visible++;
}
});
$('#ingredient-modal-no-results').toggleClass('d-none', !(q.length > 0 && visible === 0));
}
$('#ingredient-modal-search').on('input', filterIngredientModalRows);
$('#modal-ingredients-pick').on('show.bs.modal', function () {
$('#ingredient-modal-search').val('');
$('#ingredient-modal-tbody .ingredient-modal-row').show();
$('#ingredient-modal-no-results').addClass('d-none');
syncIngredientModalRows();
});
$('#btn-ingredients-modal-add').on('click', function () {
var added = 0;
$('#modal-ingredients-pick .js-ingredient-modal-cb:checked:not(:disabled)').each(function () {
var id = String($(this).val());
appendIngredientRow(id);
$(this).prop('checked', false);
added++;
});
if (added > 0) {
syncIngredientModalRows();
$('#modal-ingredients-pick').modal('hide');
}
});
$(document).on('click', '.ingredient-row-remove', function (ev) {
ev.preventDefault();
var $tr = $(this).closest('tr');
$tr.remove();
syncIngredientModalRows();
updateRecipeTotal();
});
// Löschen gespeicherter Inhaltsstoffe: eigenes Formular außerhalb des
// Produkt-Formulars, damit _method=DELETE nicht ins Speichern leakt.
$(document).on('click', '.js-ingredient-delete', function () {
var $btn = $(this);
if (!confirm($btn.data('confirm'))) return;
$('<form>', { method: 'post', action: $btn.data('action') })
.append($('<input>', { type: 'hidden', name: '_token', value: $('meta[name="csrf-token"]').attr('content') }))
.append($('<input>', { type: 'hidden', name: '_method', value: 'DELETE' }))
.appendTo('body')[0].submit();
});
$(document).on('input change', '.pi-gram, .pi-factor', function () {
updateEffective($(this).closest('tr'));
updateRecipeTotal();
});
refreshAllEffectives();
var $packTbody = document.getElementById('packaging-sortable-rows');
if ($packTbody && typeof Sortable !== 'undefined') {
new Sortable($packTbody, {
handle: '.packaging-drag-handle',
animation: 150,
});
}
function appendPackagingRow(id) {
id = String(id);
var pk = packagingCatalog[id];
if (!pk) {
return;
}
var wCell = '—';
if (pk.weight_grams != null && pk.weight_grams !== '') {
wCell = String(pk.weight_grams).replace('.', ',');
}
var row = $('<tr data-packaging-item-id="' + id + '">' +
'<td class="text-muted align-middle packaging-drag-handle" style="cursor:grab">&#9776;</td>' +
'<td class="align-middle"></td><td class="align-middle"></td><td class="align-middle text-right"></td>' +
'<td><input type="hidden" name="pp_packaging_item_id[]" value="' + id + '">' +
'<input type="text" name="pp_quantity[]" class="form-control form-control-sm pp-quantity" value="1" autocomplete="off"></td>' +
'<td class="align-middle"><a class="text-danger packaging-row-remove" href="#" title="{{ __('Entfernen') }}"><i class="far fa-trash-alt"></i></a></td></tr>');
row.find('td').eq(1).text(pk.name || '');
row.find('td').eq(2).text(pk.material_name || '—');
row.find('td').eq(3).text(wCell);
$('#packaging-sortable-rows').append(row);
}
function syncPackagingModalRows() {
var usedIds = {};
$('#packaging-sortable-rows tr').each(function () {
var pid = $(this).data('packaging-item-id');
if (pid) {
usedIds[String(pid)] = true;
}
});
$('#modal-packaging-pick .packaging-modal-row').each(function () {
var pid = String($(this).data('packaging-item-id'));
var inUse = !!usedIds[pid];
var $cb = $(this).find('.js-packaging-modal-cb');
$cb.prop('disabled', inUse);
$cb.attr('title', inUse ? '{{ __('Bereits im Produkt') }}' : '');
if (inUse) {
$cb.prop('checked', false);
}
$(this).toggleClass('text-muted', inUse);
$(this).css('opacity', inUse ? 0.65 : 1);
$(this).find('.js-pk-modal-name').toggleClass('text-muted', inUse);
$(this).find('.js-pk-modal-mat').toggleClass('text-muted', inUse);
});
}
function filterPackagingModalRows() {
var q = $('#packaging-modal-search').val().trim().toLowerCase();
var visible = 0;
$('#packaging-modal-tbody .packaging-modal-row').each(function () {
var hay = $(this).attr('data-packaging-search') || '';
var match = !q || hay.indexOf(q) !== -1;
$(this).toggle(match);
if (match) {
visible++;
}
});
$('#packaging-modal-no-results').toggleClass('d-none', !(q.length > 0 && visible === 0));
}
$('#packaging-modal-search').on('input', filterPackagingModalRows);
$('#modal-packaging-pick').on('show.bs.modal', function () {
$('#packaging-modal-search').val('');
$('#packaging-modal-tbody .packaging-modal-row').show();
$('#packaging-modal-no-results').addClass('d-none');
syncPackagingModalRows();
});
$('#btn-packaging-modal-add').on('click', function () {
var added = 0;
$('#modal-packaging-pick .js-packaging-modal-cb:checked:not(:disabled)').each(function () {
var id = String($(this).val());
appendPackagingRow(id);
$(this).prop('checked', false);
added++;
});
if (added > 0) {
syncPackagingModalRows();
$('#modal-packaging-pick').modal('hide');
}
});
$(document).on('click', '.packaging-row-remove', function (ev) {
ev.preventDefault();
$(this).closest('tr').remove();
syncPackagingModalRows();
});
// === Hersteller-Rezeptur (Manufacturer, mit Phasen — AP-23) ===
var $mfgContainer = document.getElementById('mfg-phases-container');
var mfgModalTargetTbody = null; // Ziel-Phase für das Rohstoff-Modal
function initMfgPhaseRowSortable(tbody) {
if (typeof Sortable === 'undefined') return;
new Sortable(tbody, {
handle: '.mfg-ingredient-drag-handle',
animation: 150,
group: 'mfg-phase-rows', // Zeilen zwischen Phasen verschiebbar
onEnd: syncMfgPhaseIndexes,
});
}
if ($mfgContainer && typeof Sortable !== 'undefined') {
new Sortable($mfgContainer, {
handle: '.mfg-phase-drag-handle',
animation: 150,
onEnd: syncMfgPhaseIndexes,
});
$('#mfg-phases-container .mfg-phase-rows').each(function () { initMfgPhaseRowSortable(this); });
}
// Hält mfg_row_phase[] (Zeile -> Block-Index) und die Phasen-Platzhalter aktuell.
function syncMfgPhaseIndexes() {
$('#mfg-phases-container .mfg-phase-block').each(function (blockIndex) {
$(this).find('.mfg-phase-name').attr('placeholder', 'Phase ' + String.fromCharCode(65 + blockIndex));
$(this).find('.mfg-phase-rows tr .mfg-row-phase').val(blockIndex);
});
}
function updateMfgEffective($row) {
var g = parseDeNumber($row.find('.mfg-gram').val());
var f = parseDeNumber($row.find('.mfg-factor').val());
var $out = $row.find('.mfg-effective');
if (!isNaN(g) && !isNaN(f)) {
$out.text((g * f).toLocaleString('de-DE', { minimumFractionDigits: 6, maximumFractionDigits: 6 }));
} else {
$out.text('—');
}
}
function updateMfgRecipeTotal() {
var total = 0, hasValue = false;
$('#mfg-phases-container .mfg-phase-rows tr').each(function () {
var v = parseDeNumber($(this).find('.mfg-gram').val());
if (!isNaN(v)) { total += v; hasValue = true; }
});
var $cell = $('#mfg-recipe-total-percent');
if (!hasValue) { $cell.text('—').removeClass('text-danger text-success'); return; }
$cell.text(total.toLocaleString('de-DE', { minimumFractionDigits: 6, maximumFractionDigits: 6 }) + ' %');
if (Math.abs(total - 100) < 0.000001) {
$cell.removeClass('text-danger').addClass('text-success').attr('title', '');
} else {
$cell.removeClass('text-success').addClass('text-danger').attr('title', 'Die Gesamtrezeptur (über alle Phasen) ergibt nicht 100 %!');
}
}
function refreshAllMfgEffectives() {
$('#mfg-phases-container .mfg-phase-rows tr').each(function () { updateMfgEffective($(this)); });
updateMfgRecipeTotal();
}
function appendMfgIngredientRow(id, targetTbody) {
id = String(id);
var ing = catalog[id];
if (!ing) return;
var $tbody = targetTbody && targetTbody.length ? targetTbody : $('#mfg-phases-container .mfg-phase-rows').first();
if (!$tbody.length) return;
var factor = ing.default_factor != null ? String(ing.default_factor).replace('.', ',') : '1,10';
var row = $('<tr data-ingredient-id="' + id + '">' +
'<td class="text-muted align-middle mfg-ingredient-drag-handle" style="cursor:grab">&#9776;</td>' +
'<td class="align-middle"></td><td class="align-middle small text-muted"></td><td class="align-middle"></td>' +
'<td><input type="hidden" name="mfg_ingredient_id[]" value="' + id + '">' +
'<input type="hidden" name="mfg_row_phase[]" class="mfg-row-phase" value="0">' +
'<input type="text" name="mfg_gram[]" class="form-control form-control-sm mfg-gram" value="" autocomplete="off" step="0.000001"></td>' +
'<td><input type="text" name="mfg_factor[]" class="form-control form-control-sm mfg-factor" value="' + factor + '" autocomplete="off"></td>' +
'<td class="align-middle mfg-effective text-right small text-muted">—</td>' +
'<td class="align-middle"><a class="text-danger mfg-ingredient-row-remove" href="#" title="Entfernen"><i class="far fa-trash-alt"></i></a></td></tr>');
row.find('td').eq(1).text(ing.name || '');
row.find('td').eq(2).text(ing.quality_name || '—');
row.find('td').eq(3).text(ing.inci || '');
$tbody.append(row);
syncMfgPhaseIndexes();
updateMfgEffective(row);
updateMfgRecipeTotal();
}
$('#btn-mfg-add-phase').on('click', function () {
var html = $('#mfg-phase-block-template').html();
var $block = $(html);
$('#mfg-phases-container').append($block);
initMfgPhaseRowSortable($block.find('.mfg-phase-rows')[0]);
syncMfgPhaseIndexes();
});
$(document).on('click', '.mfg-phase-remove', function (ev) {
ev.preventDefault();
var $block = $(this).closest('.mfg-phase-block');
var rowCount = $block.find('.mfg-phase-rows tr').length;
if ($('#mfg-phases-container .mfg-phase-block').length <= 1) {
alert('Die letzte Phase kann nicht entfernt werden.');
return;
}
if (rowCount > 0 && !confirm('Diese Phase enthält ' + rowCount + ' Rohstoff-Zeile(n), die mit entfernt werden. Fortfahren?')) {
return;
}
$block.remove();
syncMfgPhaseIndexes();
syncMfgIngredientModalRows();
updateMfgRecipeTotal();
});
$(document).on('click', '.mfg-phase-add-ingredients', function () {
mfgModalTargetTbody = $(this).closest('.mfg-phase-block').find('.mfg-phase-rows');
});
function syncMfgIngredientModalRows() {
var usedIds = {};
$('#mfg-phases-container .mfg-phase-rows tr').each(function () {
var id = $(this).data('ingredient-id');
if (id) usedIds[String(id)] = true;
});
$('#modal-mfg-ingredients-pick .mfg-ingredient-modal-row').each(function () {
var id = String($(this).data('ingredient-id'));
var inUse = !!usedIds[id];
var $cb = $(this).find('.js-mfg-ingredient-modal-cb');
$cb.prop('disabled', inUse);
if (inUse) $cb.prop('checked', false);
$(this).css('opacity', inUse ? 0.65 : 1);
});
}
$('#mfg-ingredient-modal-search').on('input', function () {
var q = $(this).val().trim().toLowerCase();
var visible = 0;
$('#mfg-ingredient-modal-tbody .mfg-ingredient-modal-row').each(function () {
var hay = $(this).attr('data-ingredient-search') || '';
var match = !q || hay.indexOf(q) !== -1;
$(this).toggle(match);
if (match) visible++;
});
$('#mfg-ingredient-modal-no-results').toggleClass('d-none', !(q.length > 0 && visible === 0));
});
$('#modal-mfg-ingredients-pick').on('show.bs.modal', function () {
$('#mfg-ingredient-modal-search').val('');
$('#mfg-ingredient-modal-tbody .mfg-ingredient-modal-row').show();
$('#mfg-ingredient-modal-no-results').addClass('d-none');
syncMfgIngredientModalRows();
});
$('#btn-mfg-ingredients-modal-add').on('click', function () {
var added = 0;
$('#modal-mfg-ingredients-pick .js-mfg-ingredient-modal-cb:checked:not(:disabled)').each(function () {
appendMfgIngredientRow(String($(this).val()), mfgModalTargetTbody);
$(this).prop('checked', false);
added++;
});
if (added > 0) { syncMfgIngredientModalRows(); $('#modal-mfg-ingredients-pick').modal('hide'); }
});
$(document).on('click', '.mfg-ingredient-row-remove', function (ev) {
ev.preventDefault();
$(this).closest('tr').remove();
syncMfgIngredientModalRows();
updateMfgRecipeTotal();
});
$(document).on('input change', '.mfg-gram, .mfg-factor', function () {
updateMfgEffective($(this).closest('tr'));
updateMfgRecipeTotal();
});
// Vor dem Absenden Block-Indizes final synchronisieren (Zeile -> Phase)
$('form').on('submit', function () {
syncMfgPhaseIndexes();
});
syncMfgPhaseIndexes();
refreshAllMfgEffectives();
function toggleShelfMonths() {
var v = $('.js-shelf-life-type:checked').val();
if (v === 'fixed') {
$('#shelf-life-months-wrap').show();
} else {
$('#shelf-life-months-wrap').hide();
}
}
$(document).on('change', '.js-shelf-life-type', toggleShelfMonths);
toggleShelfMonths();
function toggleRecipeFields() {
var noRecipe = $('#no_recipe_required').is(':checked');
$('.js-recipe-fields').toggle(!noRecipe);
}
$(document).on('change', '#no_recipe_required', toggleRecipeFields);
toggleRecipeFields();
// === Set-Bestandteile ===
var $setTbody = document.getElementById('set-sortable-rows');
if ($setTbody && typeof Sortable !== 'undefined') {
new Sortable($setTbody, {
handle: '.set-drag-handle',
animation: 150,
});
}
function appendSetRow(id) {
id = String(id);
var sp = setCatalog[id];
if (!sp) {
return;
}
var row = $('<tr data-set-product-id="' + id + '">' +
'<td class="text-muted align-middle set-drag-handle" style="cursor:grab">&#9776;</td>' +
'<td class="align-middle"></td><td class="align-middle small text-muted"></td>' +
'<td class="align-middle text-right small text-muted"></td>' +
'<td class="align-middle text-right small text-muted"></td>' +
'<td><input type="hidden" name="set_component_id[]" value="' + id + '">' +
'<input type="number" min="1" step="1" name="set_quantity[]" class="form-control form-control-sm set-quantity" value="1" autocomplete="off"></td>' +
'<td class="align-middle"><a class="text-danger set-row-remove" href="#" title="{{ __('Entfernen') }}"><i class="far fa-trash-alt"></i></a></td></tr>');
row.find('td').eq(1).text(sp.name || '');
row.find('td').eq(2).text(sp.number || '—');
row.find('td').eq(3).text(sp.weight || '—');
row.find('td').eq(4).text(sp.price || '—');
$('#set-sortable-rows').append(row);
}
function syncSetModalRows() {
var usedIds = {};
$('#set-sortable-rows tr').each(function () {
var sid = $(this).data('set-product-id');
if (sid) {
usedIds[String(sid)] = true;
}
});
$('#modal-set-pick .set-modal-row').each(function () {
var sid = String($(this).data('set-product-id'));
var inUse = !!usedIds[sid];
var $cb = $(this).find('.js-set-modal-cb');
$cb.prop('disabled', inUse);
$cb.attr('title', inUse ? '{{ __('Bereits im Set') }}' : '');
if (inUse) {
$cb.prop('checked', false);
}
$(this).css('opacity', inUse ? 0.65 : 1);
$(this).find('.js-set-modal-name').toggleClass('text-muted', inUse);
$(this).find('.js-set-modal-number').toggleClass('text-muted', inUse);
});
}
$('#set-modal-search').on('input', function () {
var q = $(this).val().trim().toLowerCase();
var visible = 0;
$('#set-modal-tbody .set-modal-row').each(function () {
var hay = $(this).attr('data-set-search') || '';
var match = !q || hay.indexOf(q) !== -1;
$(this).toggle(match);
if (match) {
visible++;
}
});
$('#set-modal-no-results').toggleClass('d-none', !(q.length > 0 && visible === 0));
});
$('#modal-set-pick').on('show.bs.modal', function () {
$('#set-modal-search').val('');
$('#set-modal-tbody .set-modal-row').show();
$('#set-modal-no-results').addClass('d-none');
syncSetModalRows();
});
$('#btn-set-modal-add').on('click', function () {
var added = 0;
$('#modal-set-pick .js-set-modal-cb:checked:not(:disabled)').each(function () {
appendSetRow(String($(this).val()));
$(this).prop('checked', false);
added++;
});
if (added > 0) {
syncSetModalRows();
$('#modal-set-pick').modal('hide');
}
});
$(document).on('click', '.set-row-remove', function (ev) {
ev.preventDefault();
$(this).closest('tr').remove();
syncSetModalRows();
});
function toggleSetMode() {
var isSet = $('#is_set').is(':checked');
$('.js-set-fields').toggle(isSet);
$('#product-section-rezeptur, #product-section-herstellerrezeptur, #product-section-verpackung, #product-section-warenwirtschaft').toggle(!isSet);
$('.js-nav-recipe').toggleClass('d-none', isSet);
}
$(document).on('change', '#is_set', toggleSetMode);
toggleSetMode();
function toggleOutOfStock() {
var indefinite = $('#out_of_stock_indefinite').is(':checked');
var active = $('#out_of_stock_active').is(':checked');
$('#out_of_stock_active').prop('disabled', indefinite);
$('.js-out-of-stock-date').toggle(active && !indefinite);
}
$(document).on('change', '#out_of_stock_active, #out_of_stock_indefinite', toggleOutOfStock);
toggleOutOfStock();
});
})(jQuery);
</script>
@endsection