control de stock en ventas y Soft Delete

This commit is contained in:
gianella
2026-05-27 19:30:06 -03:00
parent c2e442e82e
commit 82e550d923
+65 -4
View File
@@ -133,10 +133,11 @@
<div class="md:col-span-6"> <div class="md:col-span-6">
<x-forms.label value="Producto" /> <x-forms.label value="Producto" />
<select name="items[0][product_id]" class="w-full select2-product product-select"> <select name="items[0][product_id]" class="w-full select2-product product-select">
<option value="" data-price="0" selected disabled>Buscar producto...</option> <option value="" data-price="0" data-stock="0" selected disabled>Buscar producto...</option>
@foreach($products as $product) @foreach($products as $product)
<option value="{{ $product->id }}" data-price="{{ $product->price }}"> <option value="{{ $product->id }}"
{{ $product->sku }} - {{ $product->name }} (Stock: {{ $product->stock_quantity }}) data-price="{{ $product->price }}"
data-stock="{{ $product->stock_quantity }}"> {{ $product->sku }} - {{ $product->name }} (Stock: {{ $product->stock_quantity }})
</option> </option>
@endforeach @endforeach
</select> </select>
@@ -201,7 +202,29 @@
</form> </form>
</div> </div>
<div id="stock-modal" tabindex="-1" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-full max-h-full bg-black/50 backdrop-blur-sm transition-opacity duration-300 opacity-0">
<div class="relative p-4 w-full max-w-md max-h-full mx-auto mt-20 transform transition-all duration-300 scale-95 opacity-0" id="stock-modal-content">
<div class="relative bg-white rounded-xl shadow dark:bg-neutral-800 border border-gray-200 dark:border-neutral-700">
<button type="button" onclick="closeStockModal()" class="absolute top-3 end-2.5 text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-neutral-700 dark:hover:text-white transition-colors">
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
</svg>
<span class="sr-only">Cerrar</span>
</button>
<div class="p-4 md:p-5 text-center">
<svg class="mx-auto mb-4 text-yellow-500 w-14 h-14" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3Z"/>
</svg>
<h3 class="mb-2 text-xl font-bold text-gray-800 dark:text-white">¡Stock Insuficiente!</h3>
<p class="mb-6 text-sm font-normal text-gray-500 dark:text-gray-400" id="stock-modal-text">Solo quedan X unidades en stock.</p>
<button type="button" onclick="closeStockModal()" class="w-full text-neutral-900 bg-neon-lime hover:bg-[#b3e600] focus:ring-4 focus:outline-none focus:ring-lime-300 font-bold rounded-lg text-sm inline-flex justify-center items-center px-5 py-2.5 transition-colors shadow-lg shadow-neon-lime/20">
Entendido
</button>
</div>
</div>
</div>
</div>
<script type="module"> <script type="module">
let rowCount = 0; let rowCount = 0;
@@ -276,8 +299,17 @@
let select = row.find('.product-select'); let select = row.find('.product-select');
let input = row.find('.quantity-input'); let input = row.find('.quantity-input');
let option = select.find(':selected'); let option = select.find(':selected');
let price = parseFloat(option.data('price')) || 0; let price = parseFloat(option.data('price')) || 0;
let stockMaximo = parseInt(option.data('stock')) || 0; // Captura el data-stock
let qty = parseInt(input.val()) || 0; let qty = parseInt(input.val()) || 0;
if (qty > stockMaximo && stockMaximo > 0) {
openStockModal(stockMaximo); // Abre el modal lindo
qty = stockMaximo;
input.val(stockMaximo);
}
let subtotal = price * qty; let subtotal = price * qty;
row.find('.row-total').text('$' + subtotal.toFixed(2)); row.find('.row-total').text('$' + subtotal.toFixed(2));
} }
@@ -320,5 +352,34 @@
}); });
}); });
} }
function openStockModal(stockMaximo) {
const modal = document.getElementById('stock-modal');
const content = document.getElementById('stock-modal-content');
const textElement = document.getElementById('stock-modal-text');
textElement.innerText = `Solo nos quedan ${stockMaximo} unidades disponibles en el local.`;
modal.classList.remove('hidden');
modal.classList.add('flex');
void modal.offsetWidth;
modal.classList.remove('opacity-0');
content.classList.remove('scale-95', 'opacity-0');
content.classList.add('scale-100', 'opacity-100');
}
window.closeStockModal = function() {
const modal = document.getElementById('stock-modal');
const content = document.getElementById('stock-modal-content');
modal.classList.add('opacity-0');
content.classList.remove('scale-100', 'opacity-100');
content.classList.add('scale-95', 'opacity-0');
setTimeout(() => {
modal.classList.add('hidden');
modal.classList.remove('flex');
}, 300);
}
</script> </script>
</x-layout> </x-layout>