shipment Changes

This commit is contained in:
Utkarsh Khedkar
2025-12-24 13:36:50 +05:30
11 changed files with 2352 additions and 1095 deletions

View File

@@ -75,17 +75,25 @@ class AdminOrderController extends Controller
'description' => 'required|string', 'description' => 'required|string',
'ctn' => 'nullable|numeric', 'ctn' => 'nullable|numeric',
'qty' => 'nullable|numeric', 'qty' => 'nullable|numeric',
'ttl_qty' => 'nullable|numeric',
'unit' => 'nullable|string', 'unit' => 'nullable|string',
'price' => 'nullable|numeric', 'price' => 'nullable|numeric',
'ttl_amount' => 'nullable|numeric',
'cbm' => 'nullable|numeric', 'cbm' => 'nullable|numeric',
'ttl_cbm' => 'nullable|numeric',
'kg' => 'nullable|numeric', 'kg' => 'nullable|numeric',
'ttl_kg' => 'nullable|numeric',
'shop_no' => 'nullable|string', 'shop_no' => 'nullable|string',
]); ]);
// ✅ 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);
$data['ttl_qty'] = $ctn * $qty;
$data['ttl_amount'] = $data['ttl_qty'] * $price;
$data['ttl_cbm'] = $cbm * $ctn;
$data['ttl_kg'] = $ctn * $kg;
$data['order_id'] = $order->id; $data['order_id'] = $order->id;
OrderItem::create($data); OrderItem::create($data);
@@ -96,6 +104,7 @@ class AdminOrderController extends Controller
return redirect()->back()->with('success', 'Item added and totals updated.'); return redirect()->back()->with('success', 'Item added and totals updated.');
} }
public function deleteItem($id) public function deleteItem($id)
{ {
$item = OrderItem::findOrFail($id); $item = OrderItem::findOrFail($id);
@@ -500,14 +509,14 @@ class AdminOrderController extends Controller
'items.*.description' => 'required|string', 'items.*.description' => 'required|string',
'items.*.ctn' => 'nullable|numeric', 'items.*.ctn' => 'nullable|numeric',
'items.*.qty' => 'nullable|numeric', 'items.*.qty' => 'nullable|numeric',
'items.*.ttl_qty' => 'nullable|numeric',
'items.*.unit' => 'nullable|string', 'items.*.unit' => 'nullable|string',
'items.*.price' => 'nullable|numeric', 'items.*.price' => 'nullable|numeric',
'items.*.ttl_amount' => 'nullable|numeric',
'items.*.cbm' => 'nullable|numeric', 'items.*.cbm' => 'nullable|numeric',
'items.*.ttl_cbm' => 'nullable|numeric',
'items.*.kg' => 'nullable|numeric', 'items.*.kg' => 'nullable|numeric',
'items.*.ttl_kg' => 'nullable|numeric',
'items.*.shop_no' => 'nullable|string', 'items.*.shop_no' => 'nullable|string',
])['items']; ])['items'];
@@ -520,6 +529,24 @@ class AdminOrderController extends Controller
return back()->with('error', 'Add at least one item.'); 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 // 3) totals
$total_ctn = array_sum(array_column($items, 'ctn')); $total_ctn = array_sum(array_column($items, 'ctn'));
$total_qty = array_sum(array_column($items, 'qty')); $total_qty = array_sum(array_column($items, 'qty'));
@@ -635,18 +662,36 @@ class AdminOrderController extends Controller
$item = OrderItem::findOrFail($id); $item = OrderItem::findOrFail($id);
$order = $item->order; $order = $item->order;
$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',
]);
// ✅ 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([ $item->update([
'description' => $request->description, 'description' => $request->description,
'ctn' => $request->ctn, 'ctn' => $ctn,
'qty' => $request->qty, 'qty' => $qty,
'ttl_qty' => $request->ttl_qty, 'ttl_qty' => $ctn * $qty,
'unit' => $request->unit, 'unit' => $request->unit,
'price' => $request->price, 'price' => $price,
'ttl_amount' => $request->ttl_amount, 'ttl_amount' => ($ctn * $qty) * $price,
'cbm' => $request->cbm, 'cbm' => $cbm,
'ttl_cbm' => $request->ttl_cbm, 'ttl_cbm' => $cbm * $ctn,
'kg' => $request->kg, 'kg' => $kg,
'ttl_kg' => $request->ttl_kg, 'ttl_kg' => $ctn * $kg,
'shop_no' => $request->shop_no, 'shop_no' => $request->shop_no,
]); ]);
@@ -656,6 +701,7 @@ class AdminOrderController extends Controller
return back()->with('success', 'Item updated successfully'); return back()->with('success', 'Item updated successfully');
} }
private function updateInvoiceFromOrder(Order $order) private function updateInvoiceFromOrder(Order $order)
{ {
$invoice = Invoice::where('order_id', $order->id)->first(); $invoice = Invoice::where('order_id', $order->id)->first();

Binary file not shown.

Binary file not shown.

View File

@@ -315,15 +315,6 @@ tr:hover td{ background:#fbfdff; }
border-top: 1px solid #eef3fb; border-top: 1px solid #eef3fb;
/* margin-right:550px; */ /* 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 { .pagination-info {
font-size: 13px; font-size: 13px;
@@ -2794,10 +2785,8 @@ async function submitEditEntry(e) {
function openEntryOrdersModal(entryNo) { function openEntryOrdersModal(entryNo) {
// header la entry no show kar
document.getElementById('entryOrdersEntryNo-span').textContent = `(${entryNo})`; document.getElementById('entryOrdersEntryNo-span').textContent = `(${entryNo})`;
// table clean / loading state
const tbody = document.getElementById('entryOrdersTableBody'); const tbody = document.getElementById('entryOrdersTableBody');
tbody.innerHTML = ` tbody.innerHTML = `
<tr> <tr>
@@ -2805,7 +2794,6 @@ function openEntryOrdersModal(entryNo) {
</tr> </tr>
`; `;
// API call: /admin/account/entry-orders/{entryno}
jsonFetch(`/admin/account/entry-orders/${encodeURIComponent(entryNo)}`, { jsonFetch(`/admin/account/entry-orders/${encodeURIComponent(entryNo)}`, {
method: 'GET' method: 'GET'
}) })
@@ -2830,16 +2818,10 @@ function openEntryOrdersModal(entryNo) {
} }
tbody.innerHTML = ''; tbody.innerHTML = '';
orders.forEach(order => { orders.forEach(order => {
const tr = document.createElement('tr'); const tr = document.createElement('tr');
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');
// इथे वेगवेगळी शक्य keys try कर
const amountValue = const amountValue =
order.ttl_amount ?? order.ttl_amount ??
order.ttlamount ?? order.ttlamount ??
@@ -2849,18 +2831,17 @@ function openEntryOrdersModal(entryNo) {
0; 0;
tr.innerHTML = ` tr.innerHTML = `
<td>${formattedId}</td> <td>${escapeHtml(order.order_id)}</td>
<td>${escapeHtml(order.markno ?? order.mark_no ?? '')}</td> <td>${escapeHtml(order.mark_no ?? '')}</td>
<td>${escapeHtml(order.origin ?? '')}</td> <td>${escapeHtml(order.origin ?? '')}</td>
<td>${escapeHtml(order.destination ?? '')}</td> <td>${escapeHtml(order.destination ?? '')}</td>
<td>${escapeHtml(order.ctn ?? '')}</td> <td>${escapeHtml(order.ctn ?? '')}</td>
<td>${escapeHtml(order.qty ?? '')}</td> <td>${escapeHtml(order.qty ?? '')}</td>
<td>${formatCurrency(amountValue)}</td> <td>${formatCurrency(amountValue)}</td>
`; `;
tbody.appendChild(tr); tbody.appendChild(tr);
}); });
}) })
.catch(() => { .catch(() => {
tbody.innerHTML = ` tbody.innerHTML = `
@@ -2873,6 +2854,7 @@ function openEntryOrdersModal(entryNo) {
document.getElementById('entryOrdersModal').classList.add('modal-open'); document.getElementById('entryOrdersModal').classList.add('modal-open');
} }
function closeEntryOrdersModal() { function closeEntryOrdersModal() {
document.getElementById('entryOrdersModal').classList.remove('modal-open'); document.getElementById('entryOrdersModal').classList.remove('modal-open');
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1204,6 +1204,101 @@ body, .container-fluid {
break-inside: avoid; 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;
}
</style> </style>
<div class="container-fluid py-3"> <div class="container-fluid py-3">
@@ -1667,23 +1762,97 @@ document.addEventListener('DOMContentLoaded', function() {
const tr = document.createElement('tr'); const tr = document.createElement('tr');
tr.innerHTML = ` tr.innerHTML = `
<td class="align-middle fw-bold">${index + 1}</td> <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>
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][qty]" data-field="qty"></td> <input type="text" class="form-control form-control-sm items-input"name="items[${index}][description]"data-field="description">
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][ttl_qty]" data-field="ttl_qty"></td> </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>
<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> <input type="number" class="form-control form-control-sm items-input"name="items[${index}][ctn]"data-field="ctn">
<td><input type="number" class="form-control form-control-sm items-input" name="items[${index}][cbm]" data-field="cbm" step="0.001"></td> </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>
<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> <input type="number" class="form-control form-control-sm items-input"name="items[${index}][qty]"data-field="qty">
<td><input type="text" class="form-control form-control-sm items-input" name="items[${index}][shop_no]" data-field="shop_no"></td> </td>
<td><button type="button" class="btn btn-sm btn-danger remove-row-btn">&times;</button></td>
<!-- 🔒 AUTO: TTL/QTY = CTN * QTY -->
<td>
<input type="number" class="form-control form-control-sm bg-light"name="items[${index}][ttl_qty]"data-field="ttl_qty"readonly>
</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>
<!-- 🔒 AUTO: TTL AMOUNT = TTL/QTY * PRICE -->
<td>
<input type="number" class="form-control form-control-sm bg-light"name="items[${index}][ttl_amount]"data-field="ttl_amount"step="0.001"readonly>
</td>
<td>
<input type="number" class="form-control form-control-sm items-input"name="items[${index}][cbm]"data-field="cbm"step="0.0001">
</td>
<!-- 🔒 AUTO: TTL CBM = CBM * QTY -->
<td>
<input type="number" class="form-control form-control-sm bg-light"name="items[${index}][ttl_cbm]"data-field="ttl_cbm"step="0.0001"readonly>
</td>
<td>
<input type="number" class="form-control form-control-sm items-input"name="items[${index}][kg]"data-field="kg"step="0.0001">
</td>
<!-- 🔒 AUTO: TTL KG = CTN * KG -->
<td>
<input type="number" class="form-control form-control-sm bg-light"name="items[${index}][ttl_kg]"data-field="ttl_kg"step="0.0001"readonly>
</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); 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() { function generateDefaultRows() {
itemsTableBody.innerHTML = ''; itemsTableBody.innerHTML = '';
addRow(0); addRow(0);
@@ -2094,6 +2263,9 @@ document.addEventListener('DOMContentLoaded', function() {
}); });
} }
function populateItemsTable(items) {
itemsTableBody.innerHTML = '';
function populateItemsTable(items) { function populateItemsTable(items) {
itemsTableBody.innerHTML = ''; itemsTableBody.innerHTML = '';
@@ -2102,21 +2274,21 @@ document.addEventListener('DOMContentLoaded', function() {
const row = itemsTableBody.children[index]; const row = itemsTableBody.children[index];
row.querySelector('[data-field="description"]').value = item.description ?? ''; row.querySelector('[data-field="description"]').value = item.description ?? '';
row.querySelector('[data-field="ctn"]').value = item.ctn ?? ''; row.querySelector('[data-field="ctn"]').value = item.ctn ?? 0;
row.querySelector('[data-field="qty"]').value = item.qty ?? ''; row.querySelector('[data-field="qty"]').value = item.qty ?? 0;
row.querySelector('[data-field="ttl_qty"]').value = item.ttl_qty ?? '';
row.querySelector('[data-field="unit"]').value = item.unit ?? ''; row.querySelector('[data-field="unit"]').value = item.unit ?? '';
row.querySelector('[data-field="price"]').value = item.price ?? ''; row.querySelector('[data-field="price"]').value= item.price ?? 0;
row.querySelector('[data-field="ttl_amount"]').value = item.ttl_amount ?? ''; row.querySelector('[data-field="cbm"]').value = item.cbm ?? 0;
row.querySelector('[data-field="cbm"]').value = item.cbm ?? ''; row.querySelector('[data-field="kg"]').value = item.kg ?? 0;
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="shop_no"]').value = item.shop_no ?? ''; row.querySelector('[data-field="shop_no"]').value = item.shop_no ?? '';
// 🔥 ALWAYS RECALCULATE
calculateRow(row);
}); });
reindexRows(); reindexRows();
} }
}); });
</script> </script>

File diff suppressed because it is too large Load Diff

View File

@@ -333,7 +333,11 @@ a.btn.btn-primary.position-relative .badge {
box-shadow: 0 0 0 2px #ffffff; box-shadow: 0 0 0 2px #ffffff;
} }
.custom-table th,
.custom-table td {
text-align: center;
vertical-align: middle;
}
</style> </style>

View File

@@ -1827,8 +1827,32 @@
<th>Amount ()</th> <th>Amount ()</th>
</tr> </tr>
</thead> </thead>
<tbody id="modalOrdersTableBody"> <tbody>
<!-- Orders will be populated by JavaScript -->
@forelse($availableOrders as $order)
<tr>
<td>
<input type="checkbox" name="order_ids[]" value="{{ $order->id }}">
</td>
<td>
<a href="#" class="text-primary fw-bold">{{ $order->order_id }}</a>
</td>
<td>{{ $order->origin }}</td>
<td>{{ $order->destination }}</td>
<td>{{ $order->ctn }}</td>
<td>{{ $order->qty }}</td>
<td>{{ $order->ttl_qty }}</td>
<td>{{ $order->cbm }}</td>
<td>{{ $order->ttl_cbm }}</td>
<td>{{ $order->kg }}</td>
<td>{{ $order->ttl_kg }}</td>
<td class="fw-bold text-success">{{ number_format($order->ttl_amount, 2) }}</td>
</tr>
@empty
<tr>
<td colspan="12" class="text-muted text-center py-4">No available orders to add to shipment</td>
</tr>
@endforelse
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@@ -5,6 +5,46 @@
@section('content') @section('content')
<style> <style>
/* Hide scrollbar but keep scroll functionality */
html,
body {
overflow-x: hidden !important;
width: 100%;
max-width: 100%;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
html, body {
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE & Edge */
}
html::-webkit-scrollbar,
body::-webkit-scrollbar {
display: none; /* Chrome, Safari */
}
/* GLOBAL scrollbar hide keeps scrolling */
html,
body,
.staff-add-container,
.staff-add-card {
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE / Edge */
}
html::-webkit-scrollbar,
body::-webkit-scrollbar,
.staff-add-container::-webkit-scrollbar,
.staff-add-card::-webkit-scrollbar {
display: none; /* Chrome / Safari */
}
:root { :root {
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%); --primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--secondary-gradient: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); --secondary-gradient: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
@@ -15,10 +55,15 @@
} }
body { body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh; min-height: 100vh;
padding: 20px; margin: 0;
padding: clamp(12px, 2vw, 30px);
box-sizing: border-box;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
overflow-x: hidden; /* hide horizontal only */
overflow-y: auto;
} }
/* Main Container - FLUID LIKE SHIPMENT PAGE */ /* Main Container - FLUID LIKE SHIPMENT PAGE */
@@ -29,16 +74,7 @@
/* Decorative Elements */ /* Decorative Elements */
.decorative-circle { .decorative-circle {
position: absolute; display: none;
width: 300px;
height: 300px;
border-radius: 50%;
background: var(--secondary-gradient);
opacity: 0.05;
filter: blur(40px);
z-index: 0;
top: -100px;
right: -100px;
} }
/* Main Card - FLUID BEHAVIOR */ /* Main Card - FLUID BEHAVIOR */
@@ -950,6 +986,23 @@
font-size: 0.75rem; font-size: 0.75rem;
} }
} }
.header-flex {
display: flex;
align-items: center;
gap: 20px;
text-align: left; /* override center */
}
.header-icon {
flex-shrink: 0;
font-size: 48px;
}
.header-text {
display: flex;
flex-direction: column;
}
</style> </style>
<div class="staff-add-container"> <div class="staff-add-container">
@@ -960,13 +1013,18 @@
<div class="staff-add-card"> <div class="staff-add-card">
<!-- Header --> <!-- Header -->
<div class="staff-add-header"> <div class="staff-add-header">
<div class="header-content"> <div class="header-content header-flex">
<div class="header-icon">👨‍💼</div> <div class="header-icon">👨‍💼</div>
<div class="header-text">
<h1 class="header-title">Add New Staff Member</h1> <h1 class="header-title">Add New Staff Member</h1>
<p class="header-subtitle">Complete all the steps below to add a new staff member to your team</p> <p class="header-subtitle">
Complete all the steps below to add a new staff member to your team
</p>
</div> </div>
</div> </div>
</div>
<!-- Progress Steps --> <!-- Progress Steps -->
<div class="progress-steps"> <div class="progress-steps">
<div class="step active" data-step="1"> <div class="step active" data-step="1">

View File

@@ -11,6 +11,79 @@
--shadow-lg: 0 10px 30px rgba(0, 0, 0, 0.15); --shadow-lg: 0 10px 30px rgba(0, 0, 0, 0.15);
} }
/* Hide scrollbar but allow scroll */
.hide-scrollbar {
overflow-y: auto;
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE & Edge */
}
.hide-scrollbar::-webkit-scrollbar {
display: none; /* Chrome, Safari */
}
/* =========================================== */
/* HORIZONTAL SCROLL FIXES */
/* =========================================== */
html, body {
overflow-x: hidden !important;
scrollbar-width: none;
}
.staff-edit-container,
.staff-edit-card,
.form-section,
.form-grid,
.permissions-container {
max-width: 100%;
overflow-x: hidden;
}
* {
box-sizing: border-box;
}
/* Fix grid overflow issues */
.form-grid,
.permissions-container {
min-width: 0;
}
/* Fix transform hover effects */
.permission-group:hover,
.status-option:hover {
transform: translateY(-2px) !important;
}
.permission-item:hover {
transform: translateX(3px) !important;
}
/* Ensure containers don't exceed viewport */
@media (min-width: 1200px) {
.staff-edit-card {
max-width: 95vw;
}
}
@media (min-width: 1440px) {
.staff-edit-card {
max-width: 97vw;
}
}
@media (min-width: 1600px) {
.staff-edit-card {
max-width: 98vw;
}
}
@media (min-width: 1920px) {
.staff-edit-card {
max-width: 99vw;
}
}
body { body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh; min-height: 100vh;
@@ -46,21 +119,26 @@
z-index: 10; z-index: 10;
} }
/* Fluid Header */ /* =========================================== */
/* UPDATED HEADER LAYOUT */
/* =========================================== */
.staff-header { .staff-header {
display: flex;
align-items: center;
gap: 14px;
text-align: left;
background: var(--primary-gradient); background: var(--primary-gradient);
padding: 30px 25px; /* padding: 16px 20px; */
color: white; color: white;
text-align: center;
position: relative; position: relative;
flex-wrap: wrap;
} }
.staff-avatar { .staff-avatar {
width: 80px; width: 70px;
height: 80px; height: 70px;
border-radius: 50%; border-radius: 50%;
background: white; background: white;
margin: 0 auto 15px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -68,6 +146,7 @@
color: #667eea; color: #667eea;
border: 3px solid white; border: 3px solid white;
box-shadow: 0 5px 15px rgba(0,0,0,0.2); box-shadow: 0 5px 15px rgba(0,0,0,0.2);
flex-shrink: 0;
} }
.staff-avatar-initials { .staff-avatar-initials {
@@ -78,6 +157,11 @@
-webkit-text-fill-color: transparent; -webkit-text-fill-color: transparent;
} }
.staff-header-content {
flex: 1;
min-width: 0;
}
.staff-title { .staff-title {
font-size: 1.8rem; font-size: 1.8rem;
font-weight: 700; font-weight: 700;
@@ -102,6 +186,68 @@
border: 1px solid rgba(255,255,255,0.2); border: 1px solid rgba(255,255,255,0.2);
} }
/* Mobile responsive for header */
@media (max-width: 768px) {
.staff-header {
flex-direction: column;
text-align: center;
gap: 15px;
padding: 20px 15px;
}
.staff-avatar {
margin: 0 auto;
}
.staff-header-content {
text-align: center;
}
}
/* Adjust avatar sizes for larger screens */
@media (min-width: 1200px) {
.staff-header {
gap: 30px;
padding: 40px 35px;
}
.staff-avatar {
width: 90px;
height: 90px;
}
}
@media (min-width: 1440px) {
.staff-header {
gap: 35px;
padding: 45px 40px;
}
.staff-avatar {
width: 100px;
height: 100px;
}
}
@media (min-width: 1600px) {
.staff-header {
gap: 40px;
padding: 50px 45px;
}
.staff-avatar {
width: 110px;
height: 110px;
}
}
@media (min-width: 1920px) {
.staff-header {
gap: 45px;
padding: 60px 50px;
}
}
/* Fluid Form Sections */ /* Fluid Form Sections */
.form-section { .form-section {
padding: 25px; padding: 25px;
@@ -479,7 +625,7 @@
@media (min-width: 1200px) { @media (min-width: 1200px) {
.staff-edit-card { .staff-edit-card {
margin: 0 auto; margin: 0 auto;
max-width: 95%; max-width: 95vw;
} }
.form-grid { .form-grid {
@@ -532,7 +678,7 @@
/* Extra large desktop - 1440px+ */ /* Extra large desktop - 1440px+ */
@media (min-width: 1440px) { @media (min-width: 1440px) {
.staff-edit-card { .staff-edit-card {
max-width: 97%; max-width: 97vw;
} }
.form-grid { .form-grid {
@@ -604,7 +750,7 @@
/* Ultra wide desktop - 1600px+ */ /* Ultra wide desktop - 1600px+ */
@media (min-width: 1600px) { @media (min-width: 1600px) {
.staff-edit-card { .staff-edit-card {
max-width: 98%; max-width: 98vw;
} }
.form-grid { .form-grid {
@@ -676,7 +822,7 @@
} }
.staff-edit-card { .staff-edit-card {
max-width: 99%; max-width: 99vw;
} }
.form-grid { .form-grid {
@@ -788,10 +934,12 @@
{{ strtoupper(substr($staff->name, 0, 2)) }} {{ strtoupper(substr($staff->name, 0, 2)) }}
</div> </div>
</div> </div>
<div class="staff-header-content">
<h1 class="staff-title">Edit Staff Profile</h1> <h1 class="staff-title">Edit Staff Profile</h1>
<div class="staff-subtitle">{{ $staff->name }}</div> <div class="staff-subtitle">{{ $staff->name }}</div>
<div class="employee-id-badge">{{ $staff->employee_id }}</div> <div class="employee-id-badge">{{ $staff->employee_id }}</div>
</div> </div>
</div>
<!-- Error Messages --> <!-- Error Messages -->
@if($errors->any()) @if($errors->any())