1. 實作一鍵補貨智慧重新計算邏輯:切換倉庫或機台時自動更新預覽。 2. 新增多語系支援:補齊繁中、日文、英文語系檔中的庫存/上限、重新計算等關鍵字。 3. 優化 RWD 響應式佈局:在手機版自動切換為卡片式 (Card) 佈局,提升行動裝置操作體驗。 4. 新增刪除功能:預覽清單中每一行貨道皆可獨立移除,並配合唯一辨識碼 (slot_no) 修正 state 殘留 bug。 5. 完善一鍵補貨 Modal 腳底控制項:新增手動「重新計算」按鈕與樣式優化。 6. 完成補貨單管理功能:包含新增、取消、分配人員等後台邏輯與多租戶隔離。 7. 優化庫存轉移 (Transfers) 介面與詳情面板 RWD 表現。
428 lines
25 KiB
PHP
428 lines
25 KiB
PHP
@extends('layouts.admin')
|
|
|
|
@section('content')
|
|
<script>
|
|
function replenishmentManager() {
|
|
return {
|
|
showReplenishmentModal: false,
|
|
showAutoModal: false,
|
|
showCancelModal: false,
|
|
showAssignModal: false,
|
|
fromId: '',
|
|
availableProducts: [],
|
|
allProducts: @json($products ?? []),
|
|
isLoadingProducts: false,
|
|
items: [{ product_id: '', slot_no: '', quantity: 1, current_stock: 0, max_stock: 0 }],
|
|
loading: false,
|
|
cancelOrderId: null,
|
|
assignOrderId: null,
|
|
assignUserId: '',
|
|
|
|
// Auto replenishment
|
|
autoWarehouseId: '',
|
|
autoMachineId: '',
|
|
autoNote: '',
|
|
autoSlots: [],
|
|
autoHasWarning: false,
|
|
autoInsufficient: {},
|
|
autoWarehouseStocks: {},
|
|
autoPreviewLoaded: false,
|
|
autoLoading: false,
|
|
|
|
// Details Panel
|
|
showOrderDetails: false,
|
|
detailsLoading: false,
|
|
activeOrder: null,
|
|
activeItems: [],
|
|
|
|
init() {
|
|
// 偵測 URL 參數自動開啟一鍵補貨 Modal
|
|
const params = new URLSearchParams(window.location.search);
|
|
const autoMachineId = params.get('auto_machine_id');
|
|
if (autoMachineId) {
|
|
this.$nextTick(() => {
|
|
this.autoMachineId = autoMachineId;
|
|
this.showAutoModal = true;
|
|
this.autoPreviewLoaded = false;
|
|
this.autoSlots = [];
|
|
this.autoNote = '';
|
|
|
|
// 同步 HSSelect UI
|
|
this.$nextTick(() => {
|
|
const select = document.querySelector('[name="auto_machine_id"]');
|
|
if (select && window.HSSelect) {
|
|
const inst = window.HSSelect.getInstance(select);
|
|
if (inst) inst.setValue(autoMachineId);
|
|
}
|
|
});
|
|
});
|
|
// 清除 URL 參數避免重複觸發
|
|
const url = new URL(window.location);
|
|
url.searchParams.delete('auto_machine_id');
|
|
window.history.replaceState({}, '', url);
|
|
}
|
|
},
|
|
|
|
async openOrderDetails(id) {
|
|
this.showOrderDetails = true;
|
|
this.detailsLoading = true;
|
|
this.activeOrder = null;
|
|
this.activeItems = [];
|
|
try {
|
|
const res = await fetch(`{{ url('/admin/warehouses/replenishments') }}/${id}/details`, {
|
|
headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' }
|
|
});
|
|
const data = await res.json();
|
|
if (data.success) { this.activeOrder = data.order; this.activeItems = data.items; }
|
|
} catch (e) { console.error(e); window.showToast?.('{{ __("Failed to load details") }}', 'error'); }
|
|
finally { this.detailsLoading = false; }
|
|
},
|
|
|
|
openCreateModal() {
|
|
this.items = [{ product_id: '', slot_no: '', quantity: 1, current_stock: 0, max_stock: 0 }];
|
|
this.showReplenishmentModal = true;
|
|
this.$nextTick(() => { if (window.HSStaticMethods) window.HSStaticMethods.autoInit('select'); });
|
|
},
|
|
|
|
addItem() {
|
|
this.items.push({ product_id: '', slot_no: '', quantity: 1, current_stock: 0, max_stock: 0 });
|
|
this.$nextTick(() => this.updateProductSelects());
|
|
},
|
|
removeItem(i) { if (this.items.length > 1) this.items.splice(i, 1); },
|
|
|
|
async fetchStock() {
|
|
this.availableProducts = [];
|
|
if (!this.fromId) { this.$nextTick(() => this.updateProductSelects()); return; }
|
|
this.isLoadingProducts = true;
|
|
try {
|
|
const res = await fetch('{{ route("admin.warehouses.ajax.stock") }}?warehouse_id=' + this.fromId);
|
|
const json = await res.json();
|
|
if (json.success) { this.availableProducts = json.data; this.$nextTick(() => this.updateProductSelects()); }
|
|
} catch (e) { console.error(e); }
|
|
finally { this.isLoadingProducts = false; }
|
|
},
|
|
|
|
updateProductSelects() {
|
|
this.items.forEach((item, index) => {
|
|
const wrapper = document.getElementById(`product-select-wrapper-${index}`);
|
|
if (!wrapper) return;
|
|
const oldSelect = wrapper.querySelector('select');
|
|
if (oldSelect && window.HSSelect?.getInstance(oldSelect)) {
|
|
try { window.HSSelect.getInstance(oldSelect).destroy(); } catch (e) {}
|
|
}
|
|
wrapper.innerHTML = '';
|
|
const selectEl = document.createElement('select');
|
|
selectEl.id = `product-select-${index}-${Date.now()}`;
|
|
selectEl.name = `items[${index}][product_id]`;
|
|
selectEl.required = true;
|
|
selectEl.className = 'hidden';
|
|
const products = this.fromId ? this.availableProducts : this.allProducts;
|
|
const placeholderOpt = document.createElement('option');
|
|
placeholderOpt.value = '';
|
|
placeholderOpt.textContent = '{{ __("Select Product") }}';
|
|
selectEl.appendChild(placeholderOpt);
|
|
products.forEach(p => {
|
|
const opt = document.createElement('option');
|
|
opt.value = p.id;
|
|
const stockText = p.quantity !== undefined ? ` (${'{{ __("Stock") }}'}: ${p.quantity})` : '';
|
|
opt.textContent = p.name + stockText;
|
|
opt.setAttribute('data-title', p.name + stockText);
|
|
if (item.product_id == p.id) opt.selected = true;
|
|
selectEl.appendChild(opt);
|
|
});
|
|
selectEl.setAttribute('data-hs-select', JSON.stringify({
|
|
"placeholder": "{{ __('Select Product') }}",
|
|
"toggleClasses": "hs-select-toggle luxury-select-toggle w-full text-left",
|
|
"toggleTemplate": "<button type=\"button\"><span class=\"text-slate-800 dark:text-slate-200\" data-title></span><div class=\"ms-auto\"><svg class=\"size-4 text-slate-400\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m6 9 6 6 6-6\"/></svg></div></button>",
|
|
"dropdownClasses": "hs-select-menu w-full bg-white dark:bg-slate-900 border border-slate-200 dark:border-white/10 rounded-xl shadow-2xl mt-2 z-[150] max-h-48 overflow-y-auto custom-scrollbar-thin",
|
|
"optionClasses": "hs-select-option py-2 px-3 text-sm text-slate-800 dark:text-slate-300 cursor-pointer hover:bg-slate-100 dark:hover:bg-cyan-500/10 rounded-lg",
|
|
"hasSearch": true, "searchPlaceholder": "{{ __('Search Product') }}",
|
|
"searchClasses": "block w-[calc(100%-16px)] mx-2 py-2 px-3 text-sm border-slate-200 dark:border-white/10 rounded-lg focus:border-cyan-500 focus:ring-cyan-500 bg-slate-50 dark:bg-slate-900/50 dark:text-slate-200",
|
|
"searchWrapperClasses": "sticky top-0 bg-white/95 dark:bg-slate-900/95 backdrop-blur-md p-2 z-10",
|
|
"strategy": "fixed"
|
|
}));
|
|
wrapper.appendChild(selectEl);
|
|
selectEl.addEventListener('change', (e) => { item.product_id = e.target.value; });
|
|
if (window.HSStaticMethods) window.HSStaticMethods.autoInit('select');
|
|
});
|
|
},
|
|
|
|
async submitReplenishment() {
|
|
const form = document.getElementById('replenishmentForm');
|
|
const warehouseId = this.fromId;
|
|
const machineId = form.querySelector('[name="machine_id"]')?.value;
|
|
|
|
if (!warehouseId || warehouseId === ' ') {
|
|
window.showToast?.('{{ __("Please select source warehouse") }}', 'error'); return;
|
|
}
|
|
if (!machineId || machineId === ' ') {
|
|
window.showToast?.('{{ __("Please select target machine") }}', 'error'); return;
|
|
}
|
|
if (this.items.length === 0) {
|
|
window.showToast?.('{{ __("Please add at least one item") }}', 'error'); return;
|
|
}
|
|
|
|
for (let i = 0; i < this.items.length; i++) {
|
|
if (!this.items[i].product_id) {
|
|
window.showToast?.('{{ __("Please select product for item :num") }}'.replace(':num', i+1), 'error'); return;
|
|
}
|
|
if (!this.items[i].quantity || this.items[i].quantity < 1) {
|
|
window.showToast?.('{{ __("Please enter valid quantity for item :num") }}'.replace(':num', i+1), 'error'); return;
|
|
}
|
|
}
|
|
|
|
this.loading = true;
|
|
try {
|
|
const formData = new FormData(form);
|
|
const response = await fetch(form.action, {
|
|
method: 'POST', body: formData,
|
|
headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json', 'X-CSRF-TOKEN': '{{ csrf_token() }}' }
|
|
});
|
|
const result = await response.json();
|
|
if (response.ok && result.success) {
|
|
this.showReplenishmentModal = false;
|
|
window.showToast?.(result.message, 'success');
|
|
this.fetchTabData();
|
|
} else if (response.status === 422) {
|
|
const firstError = Object.values(result.errors || {})[0]?.[0] || '{{ __("Validation failed") }}';
|
|
window.showToast?.(firstError, 'error');
|
|
} else { window.showToast?.(result.message || '{{ __("System error") }}', 'error'); }
|
|
} catch (e) { console.error(e); window.showToast?.('{{ __("System Error") }}', 'error'); }
|
|
finally { this.loading = false; }
|
|
},
|
|
|
|
// 一鍵補貨預覽
|
|
async loadAutoPreview() {
|
|
if (!this.autoWarehouseId || this.autoWarehouseId === ' ' || !this.autoMachineId || this.autoMachineId === ' ') {
|
|
window.showToast?.('{{ __("Please select warehouse and machine") }}', 'error'); return;
|
|
}
|
|
this.autoLoading = true;
|
|
try {
|
|
const res = await fetch('{{ route("admin.warehouses.replenishments.auto") }}', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json', 'X-CSRF-TOKEN': '{{ csrf_token() }}' },
|
|
body: JSON.stringify({ warehouse_id: this.autoWarehouseId, machine_id: this.autoMachineId })
|
|
});
|
|
const data = await res.json();
|
|
if (data.success && data.preview) {
|
|
this.autoSlots = data.slots;
|
|
this.autoHasWarning = data.has_warning;
|
|
this.autoInsufficient = data.insufficient || {};
|
|
this.autoWarehouseStocks = data.warehouse_stocks || {};
|
|
this.autoPreviewLoaded = true;
|
|
} else {
|
|
window.showToast?.(data.message || '{{ __("Failed to load preview") }}', 'error');
|
|
}
|
|
} catch (e) { console.error(e); window.showToast?.('{{ __("System Error") }}', 'error'); }
|
|
finally { this.autoLoading = false; }
|
|
},
|
|
|
|
getActualFillable(index) {
|
|
const slot = this.autoSlots[index];
|
|
if (!slot) return 0;
|
|
|
|
let available = this.autoWarehouseStocks[slot.product_id] || 0;
|
|
for (let i = 0; i < index; i++) {
|
|
if (this.autoSlots[i].product_id === slot.product_id) {
|
|
available -= this.autoSlots[i].quantity;
|
|
}
|
|
}
|
|
return Math.max(0, Math.min(slot.quantity, available));
|
|
},
|
|
|
|
removeAutoSlot(idx) {
|
|
this.autoSlots.splice(idx, 1);
|
|
},
|
|
|
|
async submitAutoReplenishment() {
|
|
if (!this.autoSlots || this.autoSlots.length === 0) {
|
|
window.showToast?.('{{ __("No items to replenish") }}', 'error'); return;
|
|
}
|
|
|
|
this.autoLoading = true;
|
|
const items = this.autoSlots.map(s => ({
|
|
slot_no: s.slot_no,
|
|
product_id: s.product_id,
|
|
quantity: s.quantity,
|
|
current_stock: s.current_stock,
|
|
max_stock: s.max_stock,
|
|
}));
|
|
|
|
try {
|
|
const res = await fetch('{{ route("admin.warehouses.replenishments.auto") }}', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json', 'X-CSRF-TOKEN': '{{ csrf_token() }}' },
|
|
body: JSON.stringify({
|
|
warehouse_id: this.autoWarehouseId,
|
|
machine_id: this.autoMachineId,
|
|
note: this.autoNote,
|
|
items
|
|
})
|
|
});
|
|
const data = await res.json();
|
|
if (data.success) {
|
|
this.showAutoModal = false;
|
|
this.autoPreviewLoaded = false;
|
|
this.autoSlots = [];
|
|
window.showToast?.(data.message, 'success');
|
|
this.fetchTabData();
|
|
} else {
|
|
window.showToast?.(data.message || '{{ __("Creation failed") }}', 'error');
|
|
}
|
|
} catch (e) { console.error(e); window.showToast?.('{{ __("System Error") }}', 'error'); }
|
|
finally { this.autoLoading = false; }
|
|
},
|
|
|
|
// 狀態推進
|
|
async advanceStatus(orderId, newStatus) {
|
|
const labels = { prepared: '{{ __("Confirm Prepare") }}', delivering: '{{ __("Start Delivery") }}', completed: '{{ __("Confirm Complete") }}' };
|
|
if (!confirm(labels[newStatus] + '?')) return;
|
|
this.loading = true;
|
|
try {
|
|
const res = await fetch(`{{ url('/admin/warehouses/replenishments') }}/${orderId}/status`, {
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json', 'X-CSRF-TOKEN': '{{ csrf_token() }}' },
|
|
body: JSON.stringify({ status: newStatus })
|
|
});
|
|
const data = await res.json();
|
|
if (data.success) { window.showToast?.(data.message, 'success'); this.fetchTabData(); }
|
|
else { window.showToast?.(data.message || '{{ __("Operation failed") }}', 'error'); }
|
|
} catch (e) { console.error(e); window.showToast?.('{{ __("System Error") }}', 'error'); }
|
|
finally { this.loading = false; }
|
|
},
|
|
|
|
// 取消
|
|
confirmCancel(orderId) { this.cancelOrderId = orderId; this.showCancelModal = true; },
|
|
async executeCancel() {
|
|
this.loading = true;
|
|
try {
|
|
const res = await fetch(`{{ url('/admin/warehouses/replenishments') }}/${this.cancelOrderId}/cancel`, {
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json', 'X-CSRF-TOKEN': '{{ csrf_token() }}' }
|
|
});
|
|
const data = await res.json();
|
|
if (data.success) {
|
|
this.showCancelModal = false;
|
|
let msg = data.message;
|
|
if (data.stock_returned) msg += ' — {{ __("Stock returned to warehouse") }}';
|
|
window.showToast?.(msg, 'success');
|
|
this.fetchTabData();
|
|
} else { window.showToast?.(data.message, 'error'); }
|
|
} catch (e) { console.error(e); window.showToast?.('{{ __("System Error") }}', 'error'); }
|
|
finally { this.loading = false; }
|
|
},
|
|
|
|
// 指派
|
|
openAssignModal(orderId) { this.assignOrderId = orderId; this.assignUserId = ''; this.showAssignModal = true; },
|
|
async executeAssign() {
|
|
if (!this.assignUserId) { window.showToast?.('{{ __("Select Personnel") }}', 'error'); return; }
|
|
this.loading = true;
|
|
try {
|
|
const res = await fetch(`{{ url('/admin/warehouses/replenishments') }}/${this.assignOrderId}/assign`, {
|
|
method: 'PATCH',
|
|
headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json', 'X-CSRF-TOKEN': '{{ csrf_token() }}' },
|
|
body: JSON.stringify({ assigned_to: this.assignUserId })
|
|
});
|
|
const data = await res.json();
|
|
if (data.success) { this.showAssignModal = false; window.showToast?.(data.message, 'success'); this.fetchTabData(); }
|
|
else { window.showToast?.(data.message, 'error'); }
|
|
} catch (e) { console.error(e); }
|
|
finally { this.loading = false; }
|
|
},
|
|
|
|
async fetchTabData(url = null) {
|
|
this.loading = true;
|
|
const container = document.getElementById('replenishments-table-container');
|
|
if (!url) {
|
|
const form = document.querySelector('form[action="{{ route('admin.warehouses.replenishments') }}"]');
|
|
url = `${form.action}?${new URLSearchParams(new FormData(form)).toString()}`;
|
|
}
|
|
try {
|
|
const res = await fetch(url, { headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' } });
|
|
const data = await res.json();
|
|
if (data.success && container) {
|
|
container.outerHTML = data.html;
|
|
this.$nextTick(() => { if (window.HSStaticMethods) window.HSStaticMethods.autoInit(); });
|
|
window.history.pushState({}, '', new URL(url, window.location.origin).toString());
|
|
}
|
|
} catch (e) { console.error(e); window.showToast?.('{{ __("Loading failed") }}', 'error'); }
|
|
finally { this.loading = false; }
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div class="space-y-3 pb-10" x-data="replenishmentManager()"
|
|
@open-details.window="openOrderDetails($event.detail.id)"
|
|
@ajax:navigate:replenishments.window.prevent="fetchTabData($event.detail.url)">
|
|
|
|
{{-- Header --}}
|
|
<div class="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
|
<div>
|
|
<h1 class="text-3xl font-black text-slate-800 dark:text-white font-display tracking-tight">{{ __('Machine Replenishment') }}</h1>
|
|
<p class="text-sm font-bold text-slate-500 dark:text-slate-400 mt-1 uppercase tracking-widest">{{ __('Create and manage replenishment orders from warehouse to machines') }}</p>
|
|
</div>
|
|
<div class="flex items-center gap-3">
|
|
<button type="button" @click="
|
|
autoWarehouseId = '';
|
|
autoMachineId = '';
|
|
autoNote = '';
|
|
autoPreviewLoaded = false;
|
|
autoSlots = [];
|
|
showAutoModal = true;
|
|
$nextTick(() => {
|
|
document.querySelectorAll('[name^=\'auto_\']').forEach(s => {
|
|
if (window.HSSelect) {
|
|
const inst = window.HSSelect.getInstance(s);
|
|
if (inst) inst.setValue(' ');
|
|
}
|
|
});
|
|
});
|
|
" class="btn-luxury-ghost border-cyan-500/30 text-cyan-600 hover:bg-cyan-50 dark:hover:bg-cyan-500/10">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" /></svg>
|
|
<span>{{ __('Auto Replenishment') }}</span>
|
|
</button>
|
|
<button type="button" @click="openCreateModal()" class="btn-luxury-primary">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /></svg>
|
|
<span>{{ __('New Replenishment') }}</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Filters --}}
|
|
<div class="luxury-card rounded-3xl p-8 animate-luxury-in">
|
|
<form id="replenishment-filter-form" action="{{ route('admin.warehouses.replenishments') }}" method="GET" class="flex flex-col md:flex-row md:items-center gap-4 mb-8">
|
|
<div class="relative group flex-1 md:max-w-[240px]">
|
|
<span class="absolute inset-y-0 left-0 flex items-center pl-4 pointer-events-none z-10">
|
|
<svg class="h-4 w-4 text-slate-400 group-focus-within:text-cyan-500 transition-colors" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
|
</span>
|
|
<input type="text" name="search_order" value="{{ request('search_order') }}" @keydown.enter.prevent="fetchTabData()" class="py-2.5 pl-12 pr-6 block w-full luxury-input" placeholder="{{ __('Search order number...') }}">
|
|
</div>
|
|
<div class="flex-1 md:max-w-[180px]">
|
|
<x-searchable-select name="status" :selected="request('status')" :placeholder="__('All Statuses')">
|
|
<option value="" data-title="{{ __('All Statuses') }}">{{ __('All Statuses') }}</option>
|
|
<option value="pending" {{ request('status') === 'pending' ? 'selected' : '' }} data-title="{{ __('Pending') }}">{{ __('Pending') }}</option>
|
|
<option value="prepared" {{ request('status') === 'prepared' ? 'selected' : '' }} data-title="{{ __('Prepared') }}">{{ __('Prepared') }}</option>
|
|
<option value="delivering" {{ request('status') === 'delivering' ? 'selected' : '' }} data-title="{{ __('Delivering') }}">{{ __('Delivering') }}</option>
|
|
<option value="completed" {{ request('status') === 'completed' ? 'selected' : '' }} data-title="{{ __('Completed') }}">{{ __('Completed') }}</option>
|
|
<option value="cancelled" {{ request('status') === 'cancelled' ? 'selected' : '' }} data-title="{{ __('Cancelled') }}">{{ __('Cancelled') }}</option>
|
|
</x-searchable-select>
|
|
</div>
|
|
<button type="button" @click="fetchTabData()" class="p-2.5 rounded-xl bg-cyan-500 text-white hover:bg-cyan-600 shadow-lg shadow-cyan-500/25" title="{{ __('Search') }}">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /></svg>
|
|
</button>
|
|
<button type="button" @click="$el.closest('form').querySelectorAll('input[type=text]').forEach(i => i.value = ''); $el.closest('form').querySelectorAll('select').forEach(s => { s.value = ' '; const inst = window.HSSelect?.getInstance(s); if(inst) inst.setValue(' '); }); fetchTabData();" class="p-2.5 rounded-xl bg-slate-100 dark:bg-slate-800 text-slate-500 hover:bg-slate-200 dark:hover:bg-slate-700" title="{{ __('Reset') }}">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" /></svg>
|
|
</button>
|
|
</form>
|
|
@include('admin.warehouses.partials.table-replenishments')
|
|
</div>
|
|
|
|
@include('admin.warehouses.partials.modal-replenishment-create')
|
|
@include('admin.warehouses.partials.modal-replenishment-auto')
|
|
@include('admin.warehouses.partials.slideover-replenishment-details')
|
|
@include('admin.warehouses.partials.modal-replenishment-cancel')
|
|
@include('admin.warehouses.partials.modal-replenishment-assign')
|
|
</div>
|
|
@endsection
|