diff --git a/app/Http/Controllers/Admin/AdminOrderController.php b/app/Http/Controllers/Admin/AdminOrderController.php index f116b96..8d887ff 100644 --- a/app/Http/Controllers/Admin/AdminOrderController.php +++ b/app/Http/Controllers/Admin/AdminOrderController.php @@ -68,33 +68,42 @@ class AdminOrderController extends Controller * ORDER ITEM MANAGEMENT (existing orders) * ---------------------------*/ public function addItem(Request $request, $orderId) - { - $order = Order::findOrFail($orderId); +{ + $order = Order::findOrFail($orderId); - $data = $request->validate([ - 'description' => 'required|string', - 'ctn' => 'nullable|numeric', - 'qty' => 'nullable|numeric', - 'ttl_qty' => 'nullable|numeric', - 'unit' => 'nullable|string', - 'price' => 'nullable|numeric', - 'ttl_amount' => 'nullable|numeric', - 'cbm' => 'nullable|numeric', - 'ttl_cbm' => 'nullable|numeric', - 'kg' => 'nullable|numeric', - 'ttl_kg' => 'nullable|numeric', - 'shop_no' => 'nullable|string', - ]); + $data = $request->validate([ + 'description' => 'required|string', + 'ctn' => 'nullable|numeric', + 'qty' => 'nullable|numeric', + 'unit' => 'nullable|string', + 'price' => 'nullable|numeric', + 'cbm' => 'nullable|numeric', + 'kg' => 'nullable|numeric', + 'shop_no' => 'nullable|string', + ]); - $data['order_id'] = $order->id; + // ✅ BACKEND CALCULATION + $ctn = (float) ($data['ctn'] ?? 0); + $qty = (float) ($data['qty'] ?? 0); + $price = (float) ($data['price'] ?? 0); + $cbm = (float) ($data['cbm'] ?? 0); + $kg = (float) ($data['kg'] ?? 0); - OrderItem::create($data); + $data['ttl_qty'] = $ctn * $qty; + $data['ttl_amount'] = $data['ttl_qty'] * $price; + $data['ttl_cbm'] = $cbm * $ctn; + $data['ttl_kg'] = $ctn * $kg; - $this->recalcTotals($order); - $this->updateInvoiceFromOrder($order); + $data['order_id'] = $order->id; + + OrderItem::create($data); + + $this->recalcTotals($order); + $this->updateInvoiceFromOrder($order); + + return redirect()->back()->with('success', 'Item added and totals updated.'); +} - return redirect()->back()->with('success', 'Item added and totals updated.'); - } public function deleteItem($id) { @@ -500,14 +509,14 @@ class AdminOrderController extends Controller 'items.*.description' => 'required|string', 'items.*.ctn' => 'nullable|numeric', 'items.*.qty' => 'nullable|numeric', - 'items.*.ttl_qty' => 'nullable|numeric', + 'items.*.unit' => 'nullable|string', 'items.*.price' => 'nullable|numeric', - 'items.*.ttl_amount' => 'nullable|numeric', + 'items.*.cbm' => 'nullable|numeric', - 'items.*.ttl_cbm' => 'nullable|numeric', + 'items.*.kg' => 'nullable|numeric', - 'items.*.ttl_kg' => 'nullable|numeric', + 'items.*.shop_no' => 'nullable|string', ])['items']; @@ -520,6 +529,24 @@ class AdminOrderController extends Controller return back()->with('error', 'Add at least one item.'); } + // ✅ BACKEND CALCULATION (DO NOT TRUST FRONTEND) + foreach ($items as &$item) { + + $ctn = (float) ($item['ctn'] ?? 0); + $qty = (float) ($item['qty'] ?? 0); + $price = (float) ($item['price'] ?? 0); + $cbm = (float) ($item['cbm'] ?? 0); + $kg = (float) ($item['kg'] ?? 0); + + // Calculated fields + $item['ttl_qty'] = $ctn * $qty; + $item['ttl_amount'] = $item['ttl_qty'] * $price; + $item['ttl_cbm'] = $cbm * $ctn; + $item['ttl_kg'] = $ctn * $kg; + } + unset($item); // VERY IMPORTANT + + // 3) totals $total_ctn = array_sum(array_column($items, 'ctn')); $total_qty = array_sum(array_column($items, 'qty')); @@ -631,30 +658,49 @@ class AdminOrderController extends Controller * UPDATE ORDER ITEM (existing orders) * ---------------------------*/ public function updateItem(Request $request, $id) - { - $item = OrderItem::findOrFail($id); - $order = $item->order; +{ + $item = OrderItem::findOrFail($id); + $order = $item->order; - $item->update([ - 'description' => $request->description, - 'ctn' => $request->ctn, - 'qty' => $request->qty, - 'ttl_qty' => $request->ttl_qty, - 'unit' => $request->unit, - 'price' => $request->price, - 'ttl_amount' => $request->ttl_amount, - 'cbm' => $request->cbm, - 'ttl_cbm' => $request->ttl_cbm, - 'kg' => $request->kg, - 'ttl_kg' => $request->ttl_kg, - 'shop_no' => $request->shop_no, - ]); + $request->validate([ + 'description' => 'required|string', + 'ctn' => 'nullable|numeric', + 'qty' => 'nullable|numeric', + 'unit' => 'nullable|string', + 'price' => 'nullable|numeric', + 'cbm' => 'nullable|numeric', + 'kg' => 'nullable|numeric', + 'shop_no' => 'nullable|string', + ]); - $this->recalcTotals($order); - $this->updateInvoiceFromOrder($order); + // ✅ BACKEND CALCULATION + $ctn = (float) ($request->ctn ?? 0); + $qty = (float) ($request->qty ?? 0); + $price = (float) ($request->price ?? 0); + $cbm = (float) ($request->cbm ?? 0); + $kg = (float) ($request->kg ?? 0); + + $item->update([ + 'description' => $request->description, + 'ctn' => $ctn, + 'qty' => $qty, + 'ttl_qty' => $ctn * $qty, + 'unit' => $request->unit, + 'price' => $price, + 'ttl_amount' => ($ctn * $qty) * $price, + 'cbm' => $cbm, + 'ttl_cbm' => $cbm * $ctn, + 'kg' => $kg, + 'ttl_kg' => $ctn * $kg, + 'shop_no' => $request->shop_no, + ]); + + $this->recalcTotals($order); + $this->updateInvoiceFromOrder($order); + + return back()->with('success', 'Item updated successfully'); +} - return back()->with('success', 'Item updated successfully'); - } private function updateInvoiceFromOrder(Order $order) { diff --git a/public/invoices/invoice-INV-2025-000048.pdf b/public/invoices/invoice-INV-2025-000048.pdf new file mode 100644 index 0000000..6bce3a0 Binary files /dev/null and b/public/invoices/invoice-INV-2025-000048.pdf differ diff --git a/public/invoices/invoice-INV-2025-000051.pdf b/public/invoices/invoice-INV-2025-000051.pdf new file mode 100644 index 0000000..82b3fa7 Binary files /dev/null and b/public/invoices/invoice-INV-2025-000051.pdf differ diff --git a/resources/views/admin/account.blade.php b/resources/views/admin/account.blade.php index 5446a56..c5f765d 100644 --- a/resources/views/admin/account.blade.php +++ b/resources/views/admin/account.blade.php @@ -315,15 +315,6 @@ tr:hover td{ background:#fbfdff; } border-top: 1px solid #eef3fb; /* margin-right:550px; */ } -.pagination-container { - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 15px; - padding: 12px 0; - border-top: 1px solid #eef3fb; - margin-right:550px; -} .pagination-info { font-size: 13px; @@ -2793,85 +2784,76 @@ async function submitEditEntry(e) { } -function openEntryOrdersModal(entryNo) { - // header la entry no show kar - document.getElementById('entryOrdersEntryNo-span').textContent = `(${entryNo})`; + function openEntryOrdersModal(entryNo) { + document.getElementById('entryOrdersEntryNo-span').textContent = `(${entryNo})`; - // table clean / loading state - const tbody = document.getElementById('entryOrdersTableBody'); - tbody.innerHTML = ` - - Loading orders... - - `; - - // API call: /admin/account/entry-orders/{entryno} - jsonFetch(`/admin/account/entry-orders/${encodeURIComponent(entryNo)}`, { - method: 'GET' - }) - .then(res => { - if (!res.success) { + const tbody = document.getElementById('entryOrdersTableBody'); tbody.innerHTML = ` - - Failed to load orders - + + Loading orders... + `; - return; - } - const orders = res.orders || []; - if (!orders.length) { - tbody.innerHTML = ` - - No orders associated with this entry - - `; - return; - } + jsonFetch(`/admin/account/entry-orders/${encodeURIComponent(entryNo)}`, { + method: 'GET' + }) + .then(res => { + if (!res.success) { + tbody.innerHTML = ` + + Failed to load orders + + `; + return; + } - tbody.innerHTML = ''; - orders.forEach(order => { - const tr = document.createElement('tr'); + const orders = res.orders || []; + if (!orders.length) { + tbody.innerHTML = ` + + No orders associated with this entry + + `; + return; + } - const idString = (order.orderid ?? order.id ?? '').toString().trim(); - const numericId = parseInt(idString, 10); - const formattedId = isNaN(numericId) - ? escapeHtml(idString) - : 'KNT-25-' + String(numericId).padStart(8, '0'); + tbody.innerHTML = ''; - // इथे वेगवेगळी शक्य keys try कर - const amountValue = - order.ttl_amount ?? - order.ttlamount ?? - order.total_amount ?? - order.order_amount ?? - order.amount ?? - 0; + orders.forEach(order => { + const tr = document.createElement('tr'); - tr.innerHTML = ` - ${formattedId} - ${escapeHtml(order.markno ?? order.mark_no ?? '')} - ${escapeHtml(order.origin ?? '')} - ${escapeHtml(order.destination ?? '')} - ${escapeHtml(order.ctn ?? '')} - ${escapeHtml(order.qty ?? '')} - ${formatCurrency(amountValue)} - `; - tbody.appendChild(tr); -}); + const amountValue = + order.ttl_amount ?? + order.ttlamount ?? + order.total_amount ?? + order.order_amount ?? + order.amount ?? + 0; + tr.innerHTML = ` + ${escapeHtml(order.order_id)} + ${escapeHtml(order.mark_no ?? '')} + ${escapeHtml(order.origin ?? '')} + ${escapeHtml(order.destination ?? '')} + ${escapeHtml(order.ctn ?? '')} + ${escapeHtml(order.qty ?? '')} + ${formatCurrency(amountValue)} + `; - }) - .catch(() => { - tbody.innerHTML = ` - - Error loading orders - - `; - }); + tbody.appendChild(tr); + }); + }) + .catch(() => { + tbody.innerHTML = ` + + Error loading orders + + `; + }); + + document.getElementById('entryOrdersModal').classList.add('modal-open'); + } - document.getElementById('entryOrdersModal').classList.add('modal-open'); -} function closeEntryOrdersModal() { document.getElementById('entryOrdersModal').classList.remove('modal-open'); diff --git a/resources/views/admin/customers_add.blade.php b/resources/views/admin/customers_add.blade.php index 27c0169..5fad95e 100644 --- a/resources/views/admin/customers_add.blade.php +++ b/resources/views/admin/customers_add.blade.php @@ -5,7 +5,42 @@ @section('content') -
- -
-
- -
-

- - Add New Customer -

+
+ +
+ +
+

+ + Add New Customer +

+
+ + +
+ + - -
-
- @csrf - -
- -
- - -
Minimum 2 characters, letters only
-
- - -
- - -
- - -
- - -
- - -
- - -
Valid email format required
-
- - -
- - -
10 digits without spaces
-
- - -
- - -
6-digit pincode
-
- - -
- - -
- - -
- - -
Premium customers get special benefits
-
- - -
- - -
Active customers can place orders
-
-
- - -
- - - Cancel - - -
-
+ + + +
+ @csrf + +
+ +
+ + +
Minimum 2 characters, letters only
+ @error('customer_name') +
{{ $message }}
+ @enderror +
+ + +
+ + + @error('company_name') +
{{ $message }}
+ @enderror +
+ + +
+ + + @error('designation') +
{{ $message }}
+ @enderror +
+ + +
+ + +
Valid email format required
+ @error('email') +
{{ $message }}
+ @enderror +
+ + +
+ + +
10 digits without spaces
+ @error('mobile_no') +
{{ $message }}
+ @enderror +
+ + +
+ + +
6-digit pincode
+ @error('pincode') +
{{ $message }}
+ @enderror +
+ + +
+ + + @error('address') +
{{ $message }}
+ @enderror +
+ + +
+ + +
Premium customers get special benefits
+ @error('customer_type') +
{{ $message }}
+ @enderror +
+ + +
+ + +
Active customers can place orders
+ @error('status') +
{{ $message }}
+ @enderror +
+
+ + +
+ + + Cancel + + +
+
@@ -492,7 +878,14 @@ textarea.form-control:focus { document.addEventListener('DOMContentLoaded', function() { const form = document.getElementById('customerForm'); const submitBtn = document.getElementById('submitBtn'); + const successMessage = document.getElementById('successMessage'); + const errorMessage = document.getElementById('errorMessage'); + const errorText = document.getElementById('errorText'); + + // Store original button content + const originalBtnContent = submitBtn.innerHTML; + // Form submission handler form.addEventListener('submit', function(e) { // Add loading state submitBtn.classList.add('loading'); @@ -510,33 +903,197 @@ document.addEventListener('DOMContentLoaded', function() { }, 1500); }, 1000); }); + // Traditional form submission fallback (if JavaScript fails) + form.setAttribute('onsubmit', 'return validateFormOnSubmit()'); - // Real-time validation - const inputs = form.querySelectorAll('input[required]'); + function validateForm() { + let isValid = true; + const requiredFields = form.querySelectorAll('[required]'); + + // Clear previous error highlights + form.querySelectorAll('.is-invalid').forEach(el => { + el.classList.remove('is-invalid'); + }); + + // Validate each required field + requiredFields.forEach(field => { + if (!field.value.trim()) { + field.classList.add('is-invalid'); + isValid = false; + } else if (field.type === 'email' && !validateEmail(field.value)) { + field.classList.add('is-invalid'); + isValid = false; + } else if (field.pattern && !new RegExp(field.pattern).test(field.value)) { + field.classList.add('is-invalid'); + isValid = false; + } + }); + + return isValid; + } + + function validateEmail(email) { + const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return re.test(email); + } + + function resetSubmitButton() { + submitBtn.classList.remove('loading'); + submitBtn.innerHTML = originalBtnContent; + submitBtn.disabled = false; + } + + // Real-time validation with improved UX + const inputs = form.querySelectorAll('input[required], select[required]'); inputs.forEach(input => { input.addEventListener('blur', function() { - if (this.value && this.checkValidity()) { - this.style.borderLeft = '2px solid #10b981'; - } else if (this.value && !this.checkValidity()) { - this.style.borderLeft = '2px solid #ef4444'; - } else { + validateField(this); + }); + + input.addEventListener('input', function() { + // Remove validation styling while user is typing + if (this.value) { + this.classList.remove('is-invalid'); this.style.borderLeft = ''; } }); }); + function validateField(field) { + const hint = field.nextElementSibling?.nextElementSibling; + + if (field.value.trim() === '') { + field.classList.add('is-invalid'); + field.style.borderLeft = '2px solid #ef4444'; + if (hint && hint.classList.contains('input-hint')) { + hint.innerHTML = `❌ This field is required`; + } + } else if (field.checkValidity()) { + field.classList.remove('is-invalid'); + field.style.borderLeft = '2px solid #10b981'; + if (hint && hint.classList.contains('input-hint')) { + hint.innerHTML = hint.getAttribute('data-original-hint') || hint.innerHTML; + } + } else { + field.classList.add('is-invalid'); + field.style.borderLeft = '2px solid #ef4444'; + if (hint && hint.classList.contains('input-hint')) { + const errorMsg = getErrorMessage(field); + hint.innerHTML = `❌ ${errorMsg}`; + } + } + } + + function getErrorMessage(field) { + if (field.type === 'email') { + return 'Please enter a valid email address'; + } + if (field.pattern === '[0-9]{10}') { + return 'Please enter 10 digits only'; + } + if (field.pattern === '[A-Za-z\\s]{2,}') { + return 'Minimum 2 letters, no numbers or special characters'; + } + return 'Please check this field'; + } + + // Store original hint text + document.querySelectorAll('.input-hint').forEach(hint => { + hint.setAttribute('data-original-hint', hint.innerHTML); + }); + // Enhanced input interactions const formControls = form.querySelectorAll('.form-control, .form-select'); formControls.forEach(control => { control.addEventListener('focus', function() { this.style.transform = 'translateY(-2px)'; + this.parentElement.style.zIndex = '1'; }); control.addEventListener('blur', function() { this.style.transform = 'translateY(0)'; + this.parentElement.style.zIndex = '0'; }); }); + + // Auto-format mobile number + const mobileInput = document.getElementById('mobile_no'); + if (mobileInput) { + mobileInput.addEventListener('input', function(e) { + let value = e.target.value.replace(/\D/g, ''); + if (value.length > 10) { + value = value.substring(0, 10); + } + e.target.value = value; + }); + } + + // Auto-format pincode + const pincodeInput = document.getElementById('pincode'); + if (pincodeInput) { + pincodeInput.addEventListener('input', function(e) { + let value = e.target.value.replace(/\D/g, ''); + if (value.length > 6) { + value = value.substring(0, 6); + } + e.target.value = value; + }); + } + + // Handle zoom level detection and adjustment + function checkZoomLevel() { + const visualViewport = window.visualViewport || window; + const layoutViewport = window; + + // Calculate zoom level (approximate) + const zoom = Math.round((visualViewport.width / layoutViewport.innerWidth) * 100); + + // Adjust spacing for different zoom levels + const root = document.documentElement; + + if (zoom > 110) { + // High zoom - reduce spacing + root.style.setProperty('--space-sm', '0.5rem'); + root.style.setProperty('--input-padding', '0.5rem'); + root.style.setProperty('--card-padding', '1rem'); + } else if (zoom < 80) { + // Low zoom - increase spacing + root.style.setProperty('--space-sm', '1rem'); + root.style.setProperty('--input-padding', '1rem'); + root.style.setProperty('--card-padding', '1.5rem'); + } else { + // Normal zoom - reset to defaults + root.style.setProperty('--space-sm', '0.75rem'); + root.style.setProperty('--input-padding', 'clamp(0.75rem, 1vw, 1rem)'); + root.style.setProperty('--card-padding', 'clamp(1rem, 2vw, 1.875rem)'); + } + } + + // Initial check + checkZoomLevel(); + + // Check on resize and zoom + window.addEventListener('resize', checkZoomLevel); + if (window.visualViewport) { + window.visualViewport.addEventListener('resize', checkZoomLevel); + } }); + +// Global validation function for traditional form submission +function validateFormOnSubmit() { + const form = document.getElementById('customerForm'); + const requiredFields = form.querySelectorAll('[required]'); + let isValid = true; + + requiredFields.forEach(field => { + if (!field.value.trim()) { + field.classList.add('is-invalid'); + isValid = false; + } + }); + + return isValid; +} @endsection \ No newline at end of file diff --git a/resources/views/admin/dashboard.blade.php b/resources/views/admin/dashboard.blade.php index 15860e2..d8d220b 100644 --- a/resources/views/admin/dashboard.blade.php +++ b/resources/views/admin/dashboard.blade.php @@ -1204,6 +1204,101 @@ body, .container-fluid { break-inside: avoid; } } +/* ===================================================== + GLOBAL EDGE-TO-EDGE + ZOOM SAFE PATCH (CSS ONLY) + ===================================================== */ + +/* 1️⃣ Kill boxed layouts on desktop & zoom */ +html, body { + width: 100%; + max-width: 100%; + overflow-x: clip; +} + +/* 2️⃣ Force container-fluid to truly span full width */ +.container-fluid { + width: 100% !important; + max-width: 100% !important; + margin: 0 !important; + padding-left: clamp(12px, 1.8vw, 28px) !important; + padding-right: clamp(12px, 1.8vw, 28px) !important; +} + +/* 3️⃣ Zoom-safe scaling (VERY IMPORTANT) */ +body { + font-size: clamp(14px, 0.95vw, 16px); +} + +/* ===================================================== + DASHBOARD CARD & GRID FIXES (NO HTML CHANGE) + ===================================================== */ + +/* 4️⃣ Make stat grids auto-adjust on zoom */ +.stats-row, +.shipment-totals-row { + display: grid !important; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)) !important; + gap: clamp(12px, 1.5vw, 20px) !important; +} + +/* 5️⃣ Prevent hover zoom breaking layout */ +.stats-card:hover, +.card:hover, +.table tbody tr:hover { + transform: translateY(-4px) !important; +} + +/* ===================================================== + TABLE ZOOM FIX (NO MORE CRUSHING / OVERFLOW) + ===================================================== */ + +/* 6️⃣ Tables behave like shipment page */ +.table-responsive { + width: 100%; + overflow-x: auto; +} + +/* 7️⃣ Remove hard min-widths that break zoom */ +.table, +.custom-table-modal, +.shipment-details-table { + width: 100% !important; + min-width: max-content !important; +} + +/* 8️⃣ Let text wrap naturally when zoomed */ +.table td, +.table th { + white-space: nowrap; +} + +/* ===================================================== + MODALS – EDGE TO EDGE WITHOUT TOUCHING MARKUP + ===================================================== */ + +.modal-xl { + max-width: 96vw !important; + width: 96vw !important; + margin: 1vh auto !important; +} + +@media (max-width: 768px) { + .modal-xl { + max-width: 100vw !important; + width: 100vw !important; + margin: 0 !important; + height: 100vh !important; + } +} + +/* ===================================================== + FINAL SAFETY – PREVENT LAYOUT SHRINK ON ZOOM + ===================================================== */ + +* { + box-sizing: border-box; +} +
@@ -1666,24 +1761,98 @@ document.addEventListener('DOMContentLoaded', function() { function addRow(index) { const tr = document.createElement('tr'); tr.innerHTML = ` - ${index + 1} - - - - - - - - - - - - - - `; + ${index + 1} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `; + itemsTableBody.appendChild(tr); } + function calculateRow(row) { + const ctn = parseFloat(row.querySelector('[data-field="ctn"]')?.value) || 0; + const qty = parseFloat(row.querySelector('[data-field="qty"]')?.value) || 0; + const price = parseFloat(row.querySelector('[data-field="price"]')?.value) || 0; + const cbm = parseFloat(row.querySelector('[data-field="cbm"]')?.value) || 0; + const kg = parseFloat(row.querySelector('[data-field="kg"]')?.value) || 0; + + const ttlQty = ctn * qty; + const ttlAmount = ttlQty * price; + const ttlCbm = cbm * ctn; + const ttlKg = ctn * kg; + + row.querySelector('[data-field="ttl_qty"]').value = ttlQty.toFixed(2); + row.querySelector('[data-field="ttl_amount"]').value = ttlAmount.toFixed(2); + row.querySelector('[data-field="ttl_cbm"]').value = ttlCbm.toFixed(3); + row.querySelector('[data-field="ttl_kg"]').value = ttlKg.toFixed(3); + } + + itemsTableBody.addEventListener('input', function (e) { + const row = e.target.closest('tr'); + if (!row) return; + + const calcFields = ['ctn', 'qty', 'price', 'cbm', 'kg']; + if (calcFields.includes(e.target.dataset.field)) { + calculateRow(row); + } + }); + + + function generateDefaultRows() { itemsTableBody.innerHTML = ''; addRow(0); @@ -2094,6 +2263,9 @@ document.addEventListener('DOMContentLoaded', function() { }); } + function populateItemsTable(items) { + itemsTableBody.innerHTML = ''; + function populateItemsTable(items) { itemsTableBody.innerHTML = ''; @@ -2102,21 +2274,21 @@ document.addEventListener('DOMContentLoaded', function() { const row = itemsTableBody.children[index]; row.querySelector('[data-field="description"]').value = item.description ?? ''; - row.querySelector('[data-field="ctn"]').value = item.ctn ?? ''; - row.querySelector('[data-field="qty"]').value = item.qty ?? ''; - row.querySelector('[data-field="ttl_qty"]').value = item.ttl_qty ?? ''; + row.querySelector('[data-field="ctn"]').value = item.ctn ?? 0; + row.querySelector('[data-field="qty"]').value = item.qty ?? 0; row.querySelector('[data-field="unit"]').value = item.unit ?? ''; - row.querySelector('[data-field="price"]').value = item.price ?? ''; - row.querySelector('[data-field="ttl_amount"]').value = item.ttl_amount ?? ''; - row.querySelector('[data-field="cbm"]').value = item.cbm ?? ''; - row.querySelector('[data-field="ttl_cbm"]').value = item.ttl_cbm ?? ''; - row.querySelector('[data-field="kg"]').value = item.kg ?? ''; - row.querySelector('[data-field="ttl_kg"]').value = item.ttl_kg ?? ''; + row.querySelector('[data-field="price"]').value= item.price ?? 0; + row.querySelector('[data-field="cbm"]').value = item.cbm ?? 0; + row.querySelector('[data-field="kg"]').value = item.kg ?? 0; row.querySelector('[data-field="shop_no"]').value = item.shop_no ?? ''; + + // 🔥 ALWAYS RECALCULATE + calculateRow(row); }); reindexRows(); } + }); diff --git a/resources/views/admin/orders_show.blade.php b/resources/views/admin/orders_show.blade.php index ca2b532..e7ca23f 100644 --- a/resources/views/admin/orders_show.blade.php +++ b/resources/views/admin/orders_show.blade.php @@ -3,203 +3,209 @@ @section('page-title', 'Order Details') @section('content') -
+{{-- FULL-WIDTH FLUID CONTAINER --}} +
+
- {{-- HEADER --}} -
-
+ {{-- MAIN CARD --}} +
+
- {{-- TOP BAR --}} -
-
-

Order Details

- @php - $status = strtolower($order->status ?? ''); - @endphp + {{-- HEADER SECTION --}} +
+
+

Order Details

+ @php + $status = strtolower($order->status ?? ''); + @endphp +

Detailed view of this shipment order

+
- Detailed view of this shipment order -
- - {{-- ADD ITEM --}} - @can('order.create') - @if($status === 'pending') - - @endif - @endcan - - - -
- - - - -
- {{-- Edit Order --}} +
+ {{-- ADD ITEM BUTTON --}} + @can('order.create') @if($status === 'pending') - @endif + @endcan - {{-- Delete Order --}} - @if($status === 'pending') -
- @csrf - @method('DELETE') - -
- @endif -
- - - -
- - {{-- EDIT ORDER FORM --}} - - - {{-- CUSTOMER INFO --}} -
-
-
-
- {{ strtoupper(substr($user->customer_name ?? 'U', 0, 1)) }} -
-
- -
-
{{ $user->customer_name ?? 'Unknown Customer' }}
-

{{ $user->company_name ?? 'N/A' }}

-

{{ $user->email ?? '' }}

-

{{ $user->mobile_no ?? '' }}

+ + +
-
-

{{ $user->address ?? '' }}

- {{ $user->pincode ?? '' }} + {{-- ACTION BUTTONS --}} +
+ @if($status === 'pending') + + +
+ @csrf + @method('DELETE') + +
+ @endif
-
- {{-- ORDER SUMMARY --}} -
-
-
-

Order ID

-
{{ $order->order_id }}
+ {{-- EDIT ORDER FORM (Hidden by default) --}} + + +
+ + {{-- CUSTOMER INFO --}} +
+
+
+
+
+ {{ strtoupper(substr($user->customer_name ?? 'U', 0, 1)) }} +
+
+
+
{{ $user->customer_name ?? 'Unknown Customer' }}
+

{{ $user->company_name ?? 'N/A' }}

+

{{ $user->email ?? '' }}

+

{{ $user->mobile_no ?? '' }}

+
+
- -
-

Mark No

-
{{ $order->mark_no }}
-
- -
-

Total Items

-
{{ $order->items->count() }}
-
- -
-

Status

- {{ ucfirst($order->status) }} +
+
+

{{ $user->address ?? '' }}

+ {{ $user->pincode ?? '' }} +
-
- {{-- ORIGIN / DESTINATION --}} -
-
-

Origin

-
{{ $order->origin }}
+ {{-- ORDER SUMMARY --}} +
+
+
+

Order ID

+
{{ $order->order_id }}
+
+
+
+
+

Mark No

+
{{ $order->mark_no }}
+
+
+
+
+

Total Items

+
{{ $order->items->count() }}
+
+
+
+
+

Status

+ {{ ucfirst($order->status) }} +
+
-
-

Destination

-
{{ $order->destination }}
+ + {{-- ORIGIN / DESTINATION --}} +
+
+
+

Origin

+
{{ $order->origin }}
+
+
+
+
+

Destination

+
{{ $order->destination }}
+
+
-
- {{-- ITEMS TABLE --}} -
- - - - - - - - - - - - - - - - - - - - - - @foreach($order->items as $index => $item) - - - - - - - - - - - - - - - - + + @endforeach + +
#DescriptionCTNQTYTTL/QTYUnitPriceTotal AmountCBMTTL CBMKGTTL KGShop NoActions
{{ $index + 1 }}{{ $item->description }}{{ $item->ctn }}{{ $item->qty }}{{ $item->ttl_qty }}{{ $item->unit }}{{ number_format($item->price, 2) }}{{ number_format($item->ttl_amount, 2) }}{{ $item->cbm }}{{ $item->ttl_cbm }}{{ $item->kg }}{{ $item->ttl_kg }}{{ $item->shop_no }} - @if($status === 'pending') - {{-- EDIT BUTTON --}} + {{-- ITEMS TABLE --}} +
+
+ + + + + + + + + + + + + + + + + + + + + @foreach($order->items as $index => $item) + + + + + + + + + + + + + + + - - - - @endforeach - -
#DescriptionCTNQTYTTL/QTYUnitPriceTotal AmountCBMTTL CBMKGTTL KGShop NoActions
{{ $index + 1 }}{{ $item->description }}{{ $item->ctn }}{{ $item->qty }}{{ $item->ttl_qty }}{{ $item->unit }}{{ number_format($item->price, 2) }}{{ number_format($item->ttl_amount, 2) }}{{ $item->cbm }}{{ $item->ttl_cbm }}{{ $item->kg }}{{ $item->ttl_kg }}{{ $item->shop_no }} +
+ @if($status === 'pending') @can('order.edit') @endcan - - {{-- DELETE BUTTON --}} + @can('order.delete')
@endcan - @endif -
-
- - - @foreach($order->items as $item) -
+
+ + {{-- TOTALS --}} +
+
+
{{ $order->ctn }}
+ Total CTN +
+
+
{{ $order->qty }}
+ Total QTY +
+
+
{{ $order->ttl_kg }}
+ Total KG +
+
+
₹{{ number_format($order->ttl_amount, 2) }}
+ Total Amount +
+
+
- @endforeach - - - {{-- TOTALS --}} -
-
-
{{ $order->ctn }}
- Total CTN -
- -
-
{{ $order->qty }}
- Total QTY -
- -
-
{{ $order->ttl_kg }}
- Total KG -
- -
-
₹{{ number_format($order->ttl_amount, 2) }}
- Total Amount -
-
-
-{{-- ADD ITEM MODAL --}} -