89 lines
6.8 KiB
PHP
89 lines
6.8 KiB
PHP
@extends('layouts.app')
|
|
@section('title', 'Inventory - UniformFlow')
|
|
@section('page-heading', 'Inventory')
|
|
@section('content')
|
|
<section class="page-intro"><div><span class="eyebrow">Stock control</span><h1>Uniform <em>inventory.</em></h1><p>Create uniform types and manage stock for every size.</p></div></section>
|
|
<div class="two-column forms-top">
|
|
<section class="panel"><div class="panel-head"><div><span class="eyebrow">Catalogue</span><h2>Add uniform type</h2></div></div>
|
|
<form method="POST" action="{{ route('inventory.items.store') }}" class="form-grid">@csrf
|
|
<label>Item code<input name="code" required placeholder="SHIRT-NVY" value="{{ old('code') }}"></label><label>Uniform name<input name="name" required placeholder="Navy work shirt" value="{{ old('name') }}"></label>
|
|
<label class="full">Sizes <span>select all applicable sizes</span>
|
|
<details class="check-dropdown" id="size-dropdown"><summary><span id="size-summary">Select sizes</span><span class="dropdown-arrow">⌄</span></summary><div class="check-options">
|
|
@foreach(['XXS','XS','S','M','L','XL','2XL','3XL','4XL','26','28','30','32','34','36','38','40','42','44','46','48'] as $size)
|
|
<label><input type="checkbox" name="sizes[]" value="{{ $size }}" @checked(in_array($size, old('sizes', [])))><span class="checkmark">✓</span><span>{{ $size }}</span></label>
|
|
@endforeach
|
|
</div></details></label><label>Low-stock level<input type="number" min="0" name="reorder_level" value="{{ old('reorder_level', 5) }}" required></label><label>Description<input name="description" placeholder="Optional notes" value="{{ old('description') }}"></label>
|
|
<button class="button primary full" type="submit">Add uniform & sizes</button></form></section>
|
|
|
|
<section class="panel"><div class="panel-head"><div><span class="eyebrow">Goods received</span><h2>Bulk add stock</h2></div></div>
|
|
<form method="POST" action="{{ route('inventory.restock') }}" class="form-grid">@csrf
|
|
<label class="full">Uniform name<select name="uniform_item_id" id="stock-item" required><option value="">Select uniform</option>@foreach($items as $item)<option value="{{ $item->id }}" @selected(old('uniform_item_id') == $item->id)>{{ $item->name }}</option>@endforeach</select></label>
|
|
<div class="full bulk-stock-picker">
|
|
<div class="bulk-picker-head"><span>Sizes and received quantities</span><b id="stock-selection-count">0 selected</b></div>
|
|
<div class="bulk-picker-placeholder" id="bulk-picker-placeholder">Select a uniform above to see its sizes.</div>
|
|
@foreach($items as $item)
|
|
<div class="bulk-size-group" data-item-id="{{ $item->id }}" hidden>
|
|
@foreach($item->variants as $variant)
|
|
@php($previousQuantity = old("stocks.{$variant->id}"))
|
|
<div class="bulk-size-row">
|
|
<label class="bulk-size-check"><input type="checkbox" class="stock-size-check" data-quantity-id="stock-qty-{{ $variant->id }}" @checked($previousQuantity !== null)><span class="checkmark">✓</span><span><strong>{{ $variant->size }}</strong><small>{{ $variant->quantity }} currently available</small></span></label>
|
|
<label class="bulk-quantity">Received<input id="stock-qty-{{ $variant->id }}" type="number" name="stocks[{{ $variant->id }}]" min="1" max="100000" value="{{ $previousQuantity ?? 1 }}" @disabled($previousQuantity === null)></label>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
<label class="full">Reference / note<input name="notes" value="{{ old('notes') }}" placeholder="PO number, supplier, delivery note..."></label><button class="button dark full" type="submit">Receive selected stock</button></form></section>
|
|
</div>
|
|
|
|
<section class="panel table-panel"><div class="panel-head"><div><span class="eyebrow">Live balances</span><h2>Stock by size</h2></div><span class="pill">{{ $items->sum(fn($i) => $i->variants->count()) }} size records</span></div>
|
|
<div class="table-wrap"><table><thead><tr><th>Uniform</th><th>Code</th><th>Size</th><th>Available</th><th>Reorder level</th><th>Status</th></tr></thead><tbody>
|
|
@forelse($items as $item)@foreach($item->variants as $variant)<tr><td><strong>{{ $item->name }}</strong></td><td>{{ $item->code }}</td><td><span class="size-badge">{{ $variant->size }}</span></td><td><strong>{{ $variant->quantity }}</strong></td><td>{{ $variant->reorder_level }}</td><td><span class="pill {{ $variant->quantity <= $variant->reorder_level ? ($variant->quantity === 0 ? 'danger' : 'warning') : 'good' }}">{{ $variant->quantity === 0 ? 'Out of stock' : ($variant->quantity <= $variant->reorder_level ? 'Low stock' : 'Healthy') }}</span></td></tr>@endforeach @empty<tr><td colspan="6" class="empty">Add your first uniform type above.</td></tr>@endforelse
|
|
</tbody></table></div></section>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const checkedSizes = () => [...document.querySelectorAll('input[name="sizes[]"]:checked')];
|
|
const updateSizeSummary = () => {
|
|
const selected = checkedSizes().map(input => input.value);
|
|
document.getElementById('size-summary').textContent = selected.length ? `${selected.length} selected: ${selected.join(', ')}` : 'Select sizes';
|
|
};
|
|
document.querySelectorAll('input[name="sizes[]"]').forEach(input => input.addEventListener('change', updateSizeSummary));
|
|
updateSizeSummary();
|
|
|
|
const itemSelect = document.getElementById('stock-item');
|
|
const groups = [...document.querySelectorAll('.bulk-size-group')];
|
|
const placeholder = document.getElementById('bulk-picker-placeholder');
|
|
const selectionCount = document.getElementById('stock-selection-count');
|
|
const updateSelectionCount = () => {
|
|
const activeGroup = groups.find(group => !group.hidden);
|
|
const selected = activeGroup ? activeGroup.querySelectorAll('.stock-size-check:checked').length : 0;
|
|
selectionCount.textContent = `${selected} selected`;
|
|
};
|
|
const updateStockSizes = () => {
|
|
groups.forEach(group => {
|
|
const active = group.dataset.itemId === itemSelect.value;
|
|
group.hidden = !active;
|
|
group.querySelectorAll('.stock-size-check').forEach(checkbox => {
|
|
if (!active) checkbox.checked = false;
|
|
const quantity = document.getElementById(checkbox.dataset.quantityId);
|
|
quantity.disabled = !active || !checkbox.checked;
|
|
quantity.required = active && checkbox.checked;
|
|
});
|
|
});
|
|
placeholder.hidden = itemSelect.value !== '';
|
|
updateSelectionCount();
|
|
};
|
|
document.querySelectorAll('.stock-size-check').forEach(checkbox => checkbox.addEventListener('change', () => {
|
|
const quantity = document.getElementById(checkbox.dataset.quantityId);
|
|
quantity.disabled = !checkbox.checked;
|
|
quantity.required = checkbox.checked;
|
|
if (checkbox.checked) quantity.focus();
|
|
updateSelectionCount();
|
|
}));
|
|
itemSelect.addEventListener('change', updateStockSizes);
|
|
updateStockSizes();
|
|
});
|
|
</script>
|
|
@endsection
|