changes of invoice and shipment

This commit is contained in:
divya abdar
2025-12-23 00:44:29 +05:30
3 changed files with 505 additions and 562 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -261,7 +261,6 @@ body, .container-fluid {
font-family: 'Inter', sans-serif;
border-bottom: 2px solid #e9ecef;
}
.table thead th:first-child { border-radius: 9px 0 0 0;}
.table thead th:last-child { border-radius: 0 9px 0 0;}
@@ -466,45 +465,47 @@ body, .container-fluid {
min-width: 2000px;
border-radius: 10px;
}
/* ===== CREATE ORDER MODAL STYLES ===== */
.create-order-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
width: 100vw; /* full screen */
height: 100vh; /* full screen */
background: #f8fafc; /* backdrop काढून direct page सारखा bg */
display: none;
justify-content: center;
align-items: center;
justify-content: flex-start; /* top पासून सुरू कर */
align-items: stretch; /* full height */
z-index: 9999;
overflow-y: auto; /* content scroll */
}
/* JS madhun modal.classList.add('show') already aahe */
.create-order-modal.show {
display: flex;
display: block; /* flex ऐवजी block => full page section सारखा */
}
/* Card ला full-width/height सारखं कर */
.create-order-modal .modal-card {
background: #fff;
border-radius: 16px;
box-shadow: 0 25px 50px rgba(0, 0, 0, 0.3);
width: 95%;
max-width: 900px;
max-height: 90vh;
overflow-y: auto;
border-radius: 0; /* corner radius काढला => normal page feel */
box-shadow: none; /* popup सारखा shadow काढला */
width: 100%;
max-width: 100%;
min-height: 100vh;
max-height: none;
overflow: visible;
}
.create-order-modal .modal-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px 25px;
border-radius: 16px 16px 0 0;
border-radius: 0;
display: flex;
justify-content: space-between;
align-items: center;
}
.create-order-modal .modal-title {
font-size: 1.4rem;
font-weight: 700;
@@ -630,6 +631,13 @@ body, .container-fluid {
font-family: 'Inter', sans-serif;
}
/* items table inputs */
.items-input {
width: 100%;
padding: 4px 6px;
font-size: 13px;
}
/* ===== ORDER DETAILS MODAL STYLES ===== */
.modal.fade .modal-dialog {
transition: transform 0.3s ease-out;
@@ -869,6 +877,27 @@ body, .container-fluid {
.pagination-controls {
justify-content: center;
}
.create-order-modal .modal-card {
width: 98%;
margin: 10px;
}
.create-order-modal .modal-body {
padding: 15px;
}
.create-order-modal .modal-header {
padding: 15px 20px;
}
.modal-body {
padding: 20px 15px;
}
.modal-header {
padding: 10px 15px;
}
}
/* Mobile Landscape (768px and below) */
@@ -1131,7 +1160,6 @@ body, .container-fluid {
break-inside: avoid;
}
}
</style>
<div class="container-fluid py-3">
@@ -1169,7 +1197,6 @@ body, .container-fluid {
@endcan
</div>
<div class="order-mgmt-main">
<!-- RECENT ORDERS TABLE -->
<div class="card shadow-sm">
@@ -1348,22 +1375,35 @@ body, .container-fluid {
{{-- ITEM INPUTS --}}
<h6 class="text-primary">Add Item</h6>
{{-- NEW ITEMS TABLE (INSTEAD OF SINGLE-ROW INPUTS) --}}
<div class="table-wrapper mb-3">
<table class="table table-bordered table-sm align-middle text-center" id="itemsTable">
<thead class="table-light">
<tr>
<th>#</th>
<th>Description</th>
<th>CTN</th>
<th>QTY</th>
<th>TTL/QTY</th>
<th>Unit</th>
<th>Price</th>
<th>TTL Amount</th>
<th>CBM</th>
<th>TTL CBM</th>
<th>KG</th>
<th>TTL KG</th>
<th>Shop No</th>
<th>Remove</th>
</tr>
</thead>
<tbody id="itemsTableBody">
{{-- JS will create default 2 blank rows --}}
</tbody>
</table>
</div>
<div class="row g-3">
<div class="col-md-4">
<label class="form-label">Description</label>
<input type="text" class="form-control" name="description" id="itemDescription" required placeholder="Enter item description">
</div>
<div class="col-md-2"><label class="form-label">CTN</label><input type="number" name="ctn" id="itemCtn" class="form-control" placeholder="CTN"></div>
<div class="col-md-2"><label class="form-label">QTY</label><input type="number" name="qty" id="itemQty" class="form-control" placeholder="QTY"></div>
<div class="col-md-2"><label class="form-label">TTL/QTY</label><input type="number" name="ttl_qty" id="itemTtlQty" class="form-control" placeholder="TTL/QTY"></div>
<div class="col-md-2"><label class="form-label">Unit</label><input type="text" name="unit" id="itemUnit" class="form-control" placeholder="Unit"></div>
<div class="col-md-2"><label class="form-label">Price</label><input type="number" step="0.01" name="price" id="itemPrice" class="form-control" placeholder="Price"></div>
<div class="col-md-2"><label class="form-label">TTL Amount</label><input type="number" step="0.01" name="ttl_amount" id="itemTtlAmount" class="form-control" placeholder="TTL Amount"></div>
<div class="col-md-2"><label class="form-label">CBM</label><input type="number" step="0.001" name="cbm" id="itemCbm" class="form-control" placeholder="CBM"></div>
<div class="col-md-2"><label class="form-label">TTL CBM</label><input type="number" step="0.001" name="ttl_cbm" id="itemTtlCbm" class="form-control" placeholder="TTL CBM"></div>
<div class="col-md-2"><label class="form-label">KG</label><input type="number" step="0.001" name="kg" id="itemKg" class="form-control" placeholder="KG"></div>
<div class="col-md-2"><label class="form-label">TTL KG</label><input type="number" step="0.001" name="ttl_kg" id="itemTtlKg" class="form-control" placeholder="TTL KG"></div>
<div class="col-md-3"><label class="form-label">Shop No</label><input type="text" name="shop_no" id="itemShopNo" class="form-control" placeholder="Shop No"></div>
<div class="col-md-12 text-end mt-3">
<button type="button" class="btn btn-secondary clear-form-btn" id="clearForm">
<i class="bi bi-arrow-clockwise"></i> Clear Form
@@ -1485,7 +1525,60 @@ document.addEventListener('DOMContentLoaded', function() {
const ordersPerPage = 10;
let allOrders = @json($orders->values());
// Initialize pagination
// ------- ITEMS TABLE LOGIC (NEW) -------
const itemsTableBody = document.getElementById('itemsTableBody');
function addRow(index) {
const tr = document.createElement('tr');
tr.innerHTML = `
<td class="align-middle fw-bold">${index + 1}</td>
<td><input type="text" class="form-control form-control-sm items-input" name="items[${index}][description]" data-field="description"></td>
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][ctn]" data-field="ctn"></td>
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][qty]" data-field="qty"></td>
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][ttl_qty]" data-field="ttl_qty"></td>
<td><input type="text" class="form-control form-control-sm items-input" name="items[${index}][unit]" data-field="unit"></td>
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][price]" data-field="price" step="0.01"></td>
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][ttl_amount]" data-field="ttl_amount" step="0.01"></td>
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][cbm]" data-field="cbm" step="0.001"></td>
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][ttl_cbm]" data-field="ttl_cbm" step="0.001"></td>
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][kg]" data-field="kg" step="0.001"></td>
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][ttl_kg]" data-field="ttl_kg" step="0.001"></td>
<td><input type="text" class="form-control form-control-sm items-input" name="items[${index}][shop_no]" data-field="shop_no"></td>
<td><button type="button" class="btn btn-sm btn-danger remove-row-btn">&times;</button></td>
`;
itemsTableBody.appendChild(tr);
}
function generateDefaultRows() {
itemsTableBody.innerHTML = '';
addRow(0);
addRow(1);
focusFirstInput();
}
function reindexRows() {
const rows = itemsTableBody.querySelectorAll('tr');
rows.forEach((tr, idx) => {
tr.querySelector('td:first-child').textContent = idx + 1;
tr.querySelectorAll('input').forEach(input => {
const field = input.getAttribute('data-field');
input.name = `items[${idx}][${field}]`;
});
});
}
function rowHasData(row) {
const inputs = row.querySelectorAll('input');
return Array.from(inputs).some(inp => inp.value.trim() !== '');
}
function focusFirstInput() {
const first = itemsTableBody.querySelector('tr:first-child input');
if (first) first.focus();
}
// ------- EXISTING PAGINATION INITIALIZE -------
initializePagination();
// Reset temp data function
@@ -1504,7 +1597,7 @@ document.addEventListener('DOMContentLoaded', function() {
modal.classList.add('show');
document.body.style.overflow = 'hidden';
document.querySelector('.alert-success')?.remove();
clearForm();
generateDefaultRows();
};
const closeModal = () => {
@@ -1518,11 +1611,9 @@ document.addEventListener('DOMContentLoaded', function() {
@endif
};
// Clear form function
// Clear form -> clear items table
const clearForm = () => {
['itemDescription','itemCtn','itemQty','itemTtlQty','itemUnit','itemPrice','itemTtlAmount','itemCbm','itemTtlCbm','itemKg','itemTtlKg','itemShopNo']
.forEach(id => document.getElementById(id).value = '');
document.getElementById('itemDescription').focus();
generateDefaultRows();
};
// Event listeners
@@ -1533,7 +1624,7 @@ document.addEventListener('DOMContentLoaded', function() {
modal.addEventListener('click', (e) => e.target === modal && closeModal());
document.addEventListener('keydown', (e) => e.key === 'Escape' && modal.classList.contains('show') && closeModal());
// Mark No functionality
// Mark No functionality (unchanged)
const markNoSelect = document.getElementById('markNoSelect');
if (markNoSelect) {
markNoSelect.addEventListener('change', function() {
@@ -1553,7 +1644,7 @@ document.addEventListener('DOMContentLoaded', function() {
@if(session('temp_order_items') && count(session('temp_order_items')) > 0)
modal.classList.add('show');
document.body.style.overflow = 'hidden';
clearForm();
generateDefaultRows();
@endif
// Reset confirmation
@@ -1564,16 +1655,16 @@ document.addEventListener('DOMContentLoaded', function() {
}
}));
// Order details modal functionality
// Order details modal functionality (unchanged)
document.querySelectorAll('.open-order-modal').forEach(button => {
button.addEventListener('click', function() {
let id = this.dataset.id;
let modal = new bootstrap.Modal(document.getElementById('orderDetailsModal'));
let modalInstance = new bootstrap.Modal(document.getElementById('orderDetailsModal'));
document.getElementById('orderDetailsBody').innerHTML =
"<p class='text-center text-muted'>Loading...</p>";
modal.show();
modalInstance.show();
fetch(`/admin/orders/view/${id}`)
.then(response => response.text())
@@ -1587,12 +1678,11 @@ document.addEventListener('DOMContentLoaded', function() {
});
});
/* ---------- Pagination Functions ---------- */
/* ---------- Pagination Functions (unchanged) ---------- */
function initializePagination() {
renderOrdersTable(allOrders);
updatePaginationControls();
// Bind pagination buttons
document.getElementById('prevPageBtn').addEventListener('click', goToPreviousPage);
document.getElementById('nextPageBtn').addEventListener('click', goToNextPage);
}
@@ -1624,21 +1714,17 @@ document.addEventListener('DOMContentLoaded', function() {
prevBtn.disabled = currentPage === 1;
nextBtn.disabled = currentPage === totalPages || totalPages === 0;
// Update page info text
const startIndex = (currentPage - 1) * ordersPerPage + 1;
const endIndex = Math.min(currentPage * ordersPerPage, allOrders.length);
pageInfo.textContent = `Showing ${startIndex} to ${endIndex} of ${allOrders.length} entries`;
// Generate page numbers
paginationPages.innerHTML = '';
if (totalPages <= 7) {
// Show all pages
for (let i = 1; i <= totalPages; i++) {
addPageButton(i, paginationPages);
}
} else {
// Show first page, current page range, and last page
addPageButton(1, paginationPages);
if (currentPage > 3) {
@@ -1684,7 +1770,6 @@ document.addEventListener('DOMContentLoaded', function() {
return;
}
// Calculate pagination
const startIndex = (currentPage - 1) * ordersPerPage;
const endIndex = startIndex + ordersPerPage;
const paginatedOrders = orders.slice(startIndex, endIndex);
@@ -1729,17 +1814,16 @@ document.addEventListener('DOMContentLoaded', function() {
`;
tbody.appendChild(tr);
// Re-bind order details modal for newly rendered rows
const orderLink = tr.querySelector('.open-order-modal');
if (orderLink) {
orderLink.addEventListener('click', function() {
let id = this.dataset.id;
let modal = new bootstrap.Modal(document.getElementById('orderDetailsModal'));
let modalInstance = new bootstrap.Modal(document.getElementById('orderDetailsModal'));
document.getElementById('orderDetailsBody').innerHTML =
"<p class='text-center text-muted'>Loading...</p>";
modal.show();
modalInstance.show();
fetch(`/admin/orders/view/${id}`)
.then(response => response.text())
@@ -1754,19 +1838,65 @@ document.addEventListener('DOMContentLoaded', function() {
}
});
}
// Enter key behavior for items/table
itemsTableBody.addEventListener('keydown', function(e) {
if (e.key !== 'Enter' || e.target.tagName !== 'INPUT') return;
e.preventDefault();
const currentInput = e.target;
const currentRow = currentInput.closest('tr');
const rows = Array.from(itemsTableBody.querySelectorAll('tr'));
const currentRowIndex = rows.indexOf(currentRow);
const inputs = Array.from(currentRow.querySelectorAll('input'));
const currentInputIndex = inputs.indexOf(currentInput);
const isLastRow = currentRowIndex === rows.length - 1;
const hasData = rowHasData(currentRow);
if (currentInputIndex < inputs.length - 1) {
inputs[currentInputIndex + 1].focus();
return;
}
if (!isLastRow) {
const nextRow = rows[currentRowIndex + 1];
const firstInputNextRow = nextRow.querySelector('input');
if (firstInputNextRow) firstInputNextRow.focus();
return;
}
if (isLastRow && hasData) {
const newIndex = rows.length;
addRow(newIndex);
reindexRows();
const newRow = itemsTableBody.querySelector('tr:last-child');
const firstInput = newRow.querySelector('input');
if (firstInput) firstInput.focus();
}
});
// Remove row
itemsTableBody.addEventListener('click', function(e) {
if (!e.target.classList.contains('remove-row-btn')) return;
const rows = itemsTableBody.querySelectorAll('tr');
if (rows.length <= 1) {
alert('At least one row must exist.');
return;
}
e.target.closest('tr').remove();
reindexRows();
});
});
</script>
<script>
document.addEventListener("hidden.bs.modal", function () {
// Remove Bootstrap backdrops
document.querySelectorAll(".modal-backdrop").forEach(el => el.remove());
// Fix page scroll locking
document.body.classList.remove("modal-open");
document.body.style.overflow = "";
});
</script>
@endsection

View File

@@ -133,6 +133,10 @@ Route::prefix('admin')
Route::get('/orders/view/{id}', [AdminOrderController::class, 'popup'])
->name('admin.orders.popup');
Route::post('/admin/orders/temp/add', [AdminOrderController::class, 'addTempItem'])
->name('admin.orders.temp.add');
// Route::get('/orders/{id}', [AdminOrderController::class, 'view'])
// ->name('admin.orders.view');
Route::get('/orders/{order:order_id}/see', [AdminOrderController::class, 'see'])