Account and Shipment Changes
This commit is contained in:
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Admin;
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Models\Shipment;
|
use App\Models\Shipment;
|
||||||
@@ -107,9 +106,6 @@ class ShipmentController extends Controller
|
|||||||
'order_qty' => $order->qty,
|
'order_qty' => $order->qty,
|
||||||
'order_ttl_qty' => $order->ttl_qty,
|
'order_ttl_qty' => $order->ttl_qty,
|
||||||
'order_ttl_amount' => $order->ttl_amount,
|
'order_ttl_amount' => $order->ttl_amount,
|
||||||
'order_cbm' => $order->cbm,
|
|
||||||
'order_ttl_cbm' => $order->ttl_cbm,
|
|
||||||
'order_kg' => $order->kg,
|
|
||||||
'order_ttl_kg' => $order->ttl_kg,
|
'order_ttl_kg' => $order->ttl_kg,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -117,110 +113,22 @@ class ShipmentController extends Controller
|
|||||||
return redirect()->back()->with('success', "Shipment $newShipmentId created successfully!");
|
return redirect()->back()->with('success', "Shipment $newShipmentId created successfully!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit($id)
|
/**
|
||||||
{
|
* Show shipment details (for modal popup)
|
||||||
$shipment = Shipment::with('orders')->findOrFail($id);
|
*/
|
||||||
|
|
||||||
return view('admin.shipments.show', [
|
|
||||||
'shipment' => $shipment,
|
|
||||||
'orders' => $shipment->orders,
|
|
||||||
'isViewMode' => false // This is the edit mode
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
$mode = request()->get('mode', 'view');
|
|
||||||
|
|
||||||
$shipment = Shipment::with(['items.order'])->findOrFail($id);
|
|
||||||
|
|
||||||
// Get orders from shipment items
|
|
||||||
$orders = collect();
|
|
||||||
foreach ($shipment->items as $item) {
|
|
||||||
if ($item->order) {
|
|
||||||
$orders->push($item->order);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get orders not assigned to any shipment (available orders)
|
|
||||||
$usedOrderIds = ShipmentItem::pluck('order_id')->toArray();
|
|
||||||
$availableOrders = Order::whereNotIn('id', $usedOrderIds)->get();
|
|
||||||
|
|
||||||
return view('admin.view-shipment', [
|
|
||||||
'shipment' => $shipment,
|
|
||||||
'orders' => $orders,
|
|
||||||
'mode' => $mode,
|
|
||||||
'availableOrders' => $availableOrders
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addOrders(Request $request, $id)
|
|
||||||
{
|
|
||||||
$request->validate([
|
|
||||||
'order_ids' => 'required|array|min:1'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$shipment = Shipment::findOrFail($id);
|
$shipment = Shipment::findOrFail($id);
|
||||||
$orderIds = $request->order_ids;
|
|
||||||
|
|
||||||
DB::beginTransaction();
|
// Load full order data from orders table
|
||||||
|
$orders = Order::whereIn('id',
|
||||||
try {
|
ShipmentItem::where('shipment_id', $id)->pluck('order_id')
|
||||||
$orders = Order::whereIn('id', $orderIds)->get();
|
)->get();
|
||||||
$addedOrders = [];
|
|
||||||
|
|
||||||
foreach ($orders as $order) {
|
|
||||||
// Prevent duplicates
|
|
||||||
if (ShipmentItem::where('shipment_id', $shipment->id)->where('order_id', $order->id)->exists()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShipmentItem::create([
|
|
||||||
'shipment_id' => $shipment->id,
|
|
||||||
'order_id' => $order->id,
|
|
||||||
'order_ctn' => $order->ctn,
|
|
||||||
'order_qty' => $order->qty,
|
|
||||||
'order_ttl_qty' => $order->ttl_qty,
|
|
||||||
'order_ttl_amount' => $order->ttl_amount,
|
|
||||||
'order_cbm' => $order->cbm,
|
|
||||||
'order_ttl_cbm' => $order->ttl_cbm,
|
|
||||||
'order_kg' => $order->kg,
|
|
||||||
'order_ttl_kg' => $order->ttl_kg,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$addedOrders[] = $order;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recalculate totals
|
|
||||||
$this->recalculateShipmentTotals($shipment->id);
|
|
||||||
|
|
||||||
DB::commit();
|
|
||||||
|
|
||||||
$shipment->refresh();
|
|
||||||
$shipment->load('items.order');
|
|
||||||
|
|
||||||
// Get updated orders list
|
|
||||||
$updatedOrders = collect();
|
|
||||||
foreach ($shipment->items as $item) {
|
|
||||||
if ($item->order) {
|
|
||||||
$updatedOrders->push($item->order);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => true,
|
|
||||||
'message' => 'Orders added to shipment successfully.',
|
|
||||||
'shipment' => $shipment,
|
'shipment' => $shipment,
|
||||||
'orders' => $addedOrders
|
'orders' => $orders
|
||||||
]);
|
]);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
DB::rollBack();
|
|
||||||
return response()->json([
|
|
||||||
'success' => false,
|
|
||||||
'message' => 'Failed to add orders: ' . $e->getMessage()
|
|
||||||
], 500);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -301,77 +209,4 @@ class ShipmentController extends Controller
|
|||||||
return redirect()->route('admin.shipments')
|
return redirect()->route('admin.shipments')
|
||||||
->with('success', 'Shipment deleted successfully.');
|
->with('success', 'Shipment deleted successfully.');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function removeOrder(Request $request)
|
|
||||||
{
|
|
||||||
$request->validate([
|
|
||||||
'shipment_id' => 'required|exists:shipments,id',
|
|
||||||
'order_id' => 'required|exists:orders,id'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$shipmentId = $request->shipment_id;
|
|
||||||
$orderId = $request->order_id;
|
|
||||||
|
|
||||||
// Get order data before deletion
|
|
||||||
$order = Order::findOrFail($orderId);
|
|
||||||
|
|
||||||
// Delete pivot entry
|
|
||||||
ShipmentItem::where('shipment_id', $shipmentId)
|
|
||||||
->where('order_id', $orderId)
|
|
||||||
->delete();
|
|
||||||
|
|
||||||
// Recalculate totals
|
|
||||||
$shipment = $this->recalculateShipmentTotals($shipmentId);
|
|
||||||
|
|
||||||
if ($request->ajax() || $request->wantsJson()) {
|
|
||||||
return response()->json([
|
|
||||||
'success' => true,
|
|
||||||
'message' => 'Order removed successfully.',
|
|
||||||
'order' => $order,
|
|
||||||
'shipment' => $shipment
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return back()->with('success', 'Order removed successfully.');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function recalculateShipmentTotals($shipmentId)
|
|
||||||
{
|
|
||||||
$shipment = Shipment::with('items')->findOrFail($shipmentId);
|
|
||||||
|
|
||||||
// Use the shipment items to calculate totals
|
|
||||||
$shipment->total_ctn = $shipment->items->sum('order_ctn');
|
|
||||||
$shipment->total_qty = $shipment->items->sum('order_qty');
|
|
||||||
$shipment->total_ttl_qty = $shipment->items->sum('order_ttl_qty');
|
|
||||||
$shipment->total_amount = $shipment->items->sum('order_ttl_amount');
|
|
||||||
$shipment->total_cbm = $shipment->items->sum('order_cbm');
|
|
||||||
$shipment->total_ttl_cbm = $shipment->items->sum('order_ttl_cbm');
|
|
||||||
$shipment->total_kg = $shipment->items->sum('order_kg');
|
|
||||||
$shipment->total_ttl_kg = $shipment->items->sum('order_ttl_kg');
|
|
||||||
|
|
||||||
$shipment->save();
|
|
||||||
$shipment->refresh(); // Refresh to get updated data
|
|
||||||
|
|
||||||
return $shipment;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper method to get available orders for a shipment
|
|
||||||
public function getAvailableOrders($shipmentId)
|
|
||||||
{
|
|
||||||
$shipment = Shipment::findOrFail($shipmentId);
|
|
||||||
|
|
||||||
// Get all used order IDs
|
|
||||||
$usedOrderIds = ShipmentItem::pluck('order_id')->toArray();
|
|
||||||
|
|
||||||
// Remove orders that are already in this shipment
|
|
||||||
$shipmentOrderIds = $shipment->items->pluck('order_id')->toArray();
|
|
||||||
$availableOrderIds = array_diff($usedOrderIds, $shipmentOrderIds);
|
|
||||||
|
|
||||||
$availableOrders = Order::whereNotIn('id', $availableOrderIds)->get();
|
|
||||||
|
|
||||||
return response()->json([
|
|
||||||
'success' => true,
|
|
||||||
'availableOrders' => $availableOrders
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Binary file not shown.
@@ -1413,7 +1413,13 @@ tr:hover td{ background:#fbfdff; }
|
|||||||
<input type="text" id="edit_description" name="description" required class="input" placeholder="Entry description">
|
<input type="text" id="edit_description" name="description" required class="input" placeholder="Entry description">
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label>Order Quantity</label>
|
<label>
|
||||||
|
Order Quantity
|
||||||
|
<span style="font-size:12px; color:#6b7280; margin-left:4px;">
|
||||||
|
(Auto Update)
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
id="edit_order_quantity"
|
id="edit_order_quantity"
|
||||||
@@ -1425,19 +1431,21 @@ tr:hover td{ background:#fbfdff; }
|
|||||||
style="cursor:pointer;"
|
style="cursor:pointer;"
|
||||||
onclick="openEntryOrdersModal(document.getElementById('edit_entry_no').value)"
|
onclick="openEntryOrdersModal(document.getElementById('edit_entry_no').value)"
|
||||||
>
|
>
|
||||||
|
|
||||||
<small class="helper-note">
|
<small class="helper-note">
|
||||||
Click on quantity to view associated orders.
|
Click on quantity to view associated orders.
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
|
||||||
|
<!-- <div>
|
||||||
<label>Payment Status</label>
|
<label>Payment Status</label>
|
||||||
<select id="edit_payment_status" name="payment_status" class="input">
|
<select id="edit_payment_status" name="payment_status" class="input">
|
||||||
<option value="unpaid">Unpaid</option>
|
<option value="unpaid">Unpaid</option>
|
||||||
<option value="paid">Paid</option>
|
<option value="paid">Paid</option>
|
||||||
<option value="pending">Pending</option>
|
<option value="pending">Pending</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>-->
|
||||||
<div>
|
<div>
|
||||||
<label>Region</label>
|
<label>Region</label>
|
||||||
<select id="edit_region" name="region" class="input" required>
|
<select id="edit_region" name="region" class="input" required>
|
||||||
@@ -2182,11 +2190,24 @@ function renderPaymentTable(list){
|
|||||||
|
|
||||||
|
|
||||||
body.appendChild(tr);
|
body.appendChild(tr);
|
||||||
|
|
||||||
const btn = tr.querySelector('.toggle-switch-btn');
|
const btn = tr.querySelector('.toggle-switch-btn');
|
||||||
setToggleVisual(btn, Number(entry.toggle_pos));
|
btn.dataset.entry = entry.entry_no; // entry_no from API
|
||||||
|
btn.dataset.pos = entry.toggle_pos ?? 0;
|
||||||
|
setToggleVisual(btn, Number(btn.dataset.pos));
|
||||||
btn.addEventListener('click', () => cycleToggle(btn));
|
btn.addEventListener('click', () => cycleToggle(btn));
|
||||||
|
|
||||||
|
|
||||||
|
const actions = tr.querySelector('.action-btns');
|
||||||
|
if (actions) {
|
||||||
|
if (entry.payment_status.toLowerCase() === 'paid') {
|
||||||
|
actions.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
actions.style.display = 'flex';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (canActions) {
|
if (canActions) {
|
||||||
const editBtn = tr.querySelector('.edit-btn');
|
const editBtn = tr.querySelector('.edit-btn');
|
||||||
editBtn.addEventListener('click', () => openEditModal(entry));
|
editBtn.addEventListener('click', () => openEditModal(entry));
|
||||||
@@ -2196,7 +2217,70 @@ function renderPaymentTable(list){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function cycleToggle(btn) {
|
||||||
|
// वर्तमान position घेऊन पुढचा स्टेट कॅल्क्युलेट करा
|
||||||
|
let pos = parseInt(btn.dataset.pos || '0', 10); // 0 = unpaid, 1 = pending, 2 = paid
|
||||||
|
pos = (pos + 1) % 3;
|
||||||
|
btn.dataset.pos = pos;
|
||||||
|
setToggleVisual(btn, pos); // रंग वगैरे अपडेट
|
||||||
|
|
||||||
|
const entryNo = btn.dataset.entry;
|
||||||
|
|
||||||
|
jsonFetch('/admin/account/toggle-payment', {
|
||||||
|
method: 'POST',
|
||||||
|
body: {
|
||||||
|
entry_no: entryNo, // controller मध्ये जी नावे आहेत तीच
|
||||||
|
toggle_pos: pos
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
if (!res.success) {
|
||||||
|
alert(res.message || 'Failed to update payment status');
|
||||||
|
|
||||||
|
// error असेल तर UI परत जुन्या स्टेटला ने
|
||||||
|
pos = (pos + 2) % 3;
|
||||||
|
btn.dataset.pos = pos;
|
||||||
|
setToggleVisual(btn, pos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1) global entries array update करा (dashboard data)
|
||||||
|
if (Array.isArray(entries)) {
|
||||||
|
const idx = entries.findIndex(e => e.entry_no === entryNo);
|
||||||
|
if (idx !== -1) {
|
||||||
|
entries[idx].toggle_pos = res.entry.toggle_pos;
|
||||||
|
entries[idx].payment_status = res.entry.payment_status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) current row मधला status badge आणि actions अपडेट करा
|
||||||
|
const row = btn.closest('tr');
|
||||||
|
if (row) {
|
||||||
|
// status badge
|
||||||
|
const statusCell = row.querySelector('.status-badge');
|
||||||
|
if (statusCell) {
|
||||||
|
statusCell.textContent = res.entry.payment_status;
|
||||||
|
statusCell.className = 'status-badge ' + statusClass(res.entry.payment_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// paid झाल्यावर edit/delete लपवा
|
||||||
|
const actions = row.querySelector('.action-btns');
|
||||||
|
if (actions) {
|
||||||
|
if (res.entry.payment_status.toLowerCase() === 'paid') {
|
||||||
|
actions.style.display = 'none';
|
||||||
|
} else {
|
||||||
|
actions.style.display = 'flex'; // किंवा तुझा default layout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
alert('Network error while updating payment status');
|
||||||
|
|
||||||
|
// network error – UI मागे घे
|
||||||
|
pos = (pos + 2) % 3;
|
||||||
|
btn.dataset.pos = pos;
|
||||||
|
setToggleVisual(btn, pos);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function renderOrderTable(list){
|
function renderOrderTable(list){
|
||||||
@@ -2336,7 +2420,7 @@ function openEditModal(entry) {
|
|||||||
document.getElementById('edit_entry_no').value = entry.entry_no;
|
document.getElementById('edit_entry_no').value = entry.entry_no;
|
||||||
document.getElementById('edit_description').value = entry.description || '';
|
document.getElementById('edit_description').value = entry.description || '';
|
||||||
document.getElementById('edit_order_quantity').value = entry.order_quantity || '';
|
document.getElementById('edit_order_quantity').value = entry.order_quantity || '';
|
||||||
document.getElementById('edit_payment_status').value = entry.payment_status || 'unpaid';
|
// document.getElementById('edit_payment_status').value = entry.payment_status || 'unpaid';
|
||||||
document.getElementById('edit_region').value = entry.region || 'China';
|
document.getElementById('edit_region').value = entry.region || 'China';
|
||||||
document.getElementById('edit_amount').value = entry.amount || '';
|
document.getElementById('edit_amount').value = entry.amount || '';
|
||||||
|
|
||||||
@@ -2470,7 +2554,7 @@ async function submitEditEntry(e) {
|
|||||||
entry_no: form.entry_no.value,
|
entry_no: form.entry_no.value,
|
||||||
description: form.description.value.trim(),
|
description: form.description.value.trim(),
|
||||||
order_quantity: Number(form.order_quantity.value) || 0,
|
order_quantity: Number(form.order_quantity.value) || 0,
|
||||||
payment_status: form.payment_status.value,
|
// payment_status: form.payment_status.value,
|
||||||
region: form.region.value,
|
region: form.region.value,
|
||||||
amount: Number(form.amount.value) || 0
|
amount: Number(form.amount.value) || 0
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -63,7 +63,6 @@
|
|||||||
--hover-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
--hover-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* UPDATED: Search Bar Styles - White Background */
|
|
||||||
.search-shipment-bar {
|
.search-shipment-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -90,69 +89,9 @@
|
|||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-input-container:focus-within {
|
.search-shipment-bar > * {
|
||||||
border-color: #4361ee;
|
position: relative;
|
||||||
box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.1);
|
z-index: 1;
|
||||||
}
|
|
||||||
|
|
||||||
.search-shipment-bar input {
|
|
||||||
padding: 12px 16px;
|
|
||||||
border: none;
|
|
||||||
flex: 1;
|
|
||||||
background: transparent;
|
|
||||||
font-weight: 500;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
font-family: 'Inter', sans-serif;
|
|
||||||
font-size: 14px;
|
|
||||||
outline: none;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-shipment-bar input::placeholder {
|
|
||||||
color: #6b7280;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* UPDATED: Search Button - White with Blue Icon by default, Gradient on hover */
|
|
||||||
.search-button {
|
|
||||||
background: white;
|
|
||||||
color: #4361ee;
|
|
||||||
border: none;
|
|
||||||
padding: 12px 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
font-weight: 600;
|
|
||||||
font-family: 'Inter', sans-serif;
|
|
||||||
font-size: 14px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
border-radius: 0 10px 10px 0;
|
|
||||||
min-width: 100px;
|
|
||||||
justify-content: center;
|
|
||||||
border-left: 1px solid #d1d5db;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-input-group {
|
|
||||||
border: 1px solid #d1d5db !important;
|
|
||||||
border-radius: 8px !important;
|
|
||||||
padding: 4px !important;
|
|
||||||
background: #ffffff !important;
|
|
||||||
}
|
|
||||||
.search-button:hover {
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
color: white;
|
|
||||||
transform: translateY(-1px);
|
|
||||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-icon {
|
|
||||||
font-size: 16px;
|
|
||||||
color: #4361ee;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-button:hover .search-icon {
|
|
||||||
color: white;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-shipment-bar input,
|
.search-shipment-bar input,
|
||||||
@@ -215,26 +154,6 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* VIEW BUTTON STYLING */
|
|
||||||
.btn-view {
|
|
||||||
background: linear-gradient(135deg, #4cc9f0, #4361ee) !important;
|
|
||||||
border: none !important;
|
|
||||||
border-radius: 10px !important;
|
|
||||||
padding: 8px 14px !important;
|
|
||||||
color: white !important;
|
|
||||||
box-shadow: 0 4px 12px rgba(67, 97, 238, 0.35) !important;
|
|
||||||
transition: all 0.3s ease !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-view:hover {
|
|
||||||
transform: translateY(-2px) scale(1.05) !important;
|
|
||||||
background: linear-gradient(135deg, #3a56d4, #4cc9f0) !important;
|
|
||||||
box-shadow: 0 8px 20px rgba(67, 97, 238, 0.5) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-view i {
|
|
||||||
font-size: 16px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Card Styles */
|
/* Card Styles */
|
||||||
.card {
|
.card {
|
||||||
@@ -326,7 +245,7 @@
|
|||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* UPDATED: Status Badge Styles - ALL SAME SIZE WITH ICONS */
|
/* UPDATED: Status Badge Styles - ALL SAME SIZE */
|
||||||
.badge {
|
.badge {
|
||||||
padding: 7px 17px !important;
|
padding: 7px 17px !important;
|
||||||
border-radius: 20px !important;
|
border-radius: 20px !important;
|
||||||
@@ -339,15 +258,7 @@
|
|||||||
line-height: 1.2 !important;
|
line-height: 1.2 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Status icons */
|
/* Pending Status - SAME SIZE */
|
||||||
.status-icon {
|
|
||||||
font-size: 13px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pending Status - SAME SIZE WITH CLOCK ICON */
|
|
||||||
.badge-pending {
|
.badge-pending {
|
||||||
background: linear-gradient(135deg, #fef3c7, #fde68a) !important;
|
background: linear-gradient(135deg, #fef3c7, #fde68a) !important;
|
||||||
color: #d97706 !important;
|
color: #d97706 !important;
|
||||||
@@ -355,7 +266,7 @@
|
|||||||
width: 110px;
|
width: 110px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In Transit Status - SAME SIZE WITH TRUCK ICON */
|
/* In Transit Status - SAME SIZE */
|
||||||
.badge-in_transit {
|
.badge-in_transit {
|
||||||
background: linear-gradient(135deg, #dbeafe, #93c5fd) !important;
|
background: linear-gradient(135deg, #dbeafe, #93c5fd) !important;
|
||||||
color: #1e40af !important;
|
color: #1e40af !important;
|
||||||
@@ -363,7 +274,7 @@
|
|||||||
width: 110px;
|
width: 110px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dispatched Status - SAME SIZE WITH BOX ICON */
|
/* Dispatched Status - SAME SIZE */
|
||||||
.badge-dispatched {
|
.badge-dispatched {
|
||||||
background: linear-gradient(135deg, #e9d5ff, #c4b5fd) !important;
|
background: linear-gradient(135deg, #e9d5ff, #c4b5fd) !important;
|
||||||
color: #6b21a8 !important;
|
color: #6b21a8 !important;
|
||||||
@@ -371,7 +282,7 @@
|
|||||||
width: 110px;
|
width: 110px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delivered Status - SAME SIZE WITH CHECK ICON */
|
/* Delivered Status - SAME SIZE */
|
||||||
.badge-delivered {
|
.badge-delivered {
|
||||||
background: linear-gradient(135deg, #d1fae5, #a7f3d0) !important;
|
background: linear-gradient(135deg, #d1fae5, #a7f3d0) !important;
|
||||||
color: #065f46 !important;
|
color: #065f46 !important;
|
||||||
@@ -536,66 +447,6 @@
|
|||||||
background: #10b981;
|
background: #10b981;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NEW: View Button Styles - Icon Only */
|
|
||||||
.btn-view {
|
|
||||||
background: #4361ee;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 16px;
|
|
||||||
font-family: 'Inter', sans-serif;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-view::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: -100%;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-view:hover::before {
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-view i {
|
|
||||||
position: relative;
|
|
||||||
z-index: 2;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-view:hover {
|
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-view:hover i {
|
|
||||||
transform: scale(1.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Action buttons container */
|
|
||||||
.action-buttons {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Modal Styles */
|
/* Modal Styles */
|
||||||
.modal-content {
|
.modal-content {
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
@@ -830,9 +681,6 @@
|
|||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
position: relative;
|
position: relative;
|
||||||
color: #4361ee !important;
|
color: #4361ee !important;
|
||||||
font-family: 'Inter', sans-serif;
|
|
||||||
font-size: 14px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a.text-primary:hover {
|
a.text-primary:hover {
|
||||||
@@ -840,7 +688,7 @@
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shipment Details Modal - UPDATED TO MATCH SECOND CODE */
|
/* Shipment Details Modal */
|
||||||
.shipment-details-header {
|
.shipment-details-header {
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
color: white;
|
color: white;
|
||||||
@@ -930,7 +778,7 @@
|
|||||||
border-bottom-right-radius: 10px;
|
border-bottom-right-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shipment Totals Section - UPDATED */
|
/* Shipment Totals Section */
|
||||||
.shipment-totals {
|
.shipment-totals {
|
||||||
margin-top: 25px;
|
margin-top: 25px;
|
||||||
padding: 25px;
|
padding: 25px;
|
||||||
@@ -1214,48 +1062,8 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Edit Form Styles */
|
|
||||||
.edit-shipment-form {
|
|
||||||
background: #f8fafc;
|
|
||||||
padding: 25px;
|
|
||||||
border-radius: 12px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
border-left: 4px solid #4361ee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-save {
|
|
||||||
background: linear-gradient(135deg, #48bb78, #38a169);
|
|
||||||
color: white;
|
|
||||||
font-weight: 600;
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 10px 20px;
|
|
||||||
border: none;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-save:hover {
|
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: 0 4px 12px rgba(72, 187, 120, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-cancel-edit {
|
|
||||||
background: #f7fafc;
|
|
||||||
color: #718096;
|
|
||||||
border: 1px solid #cbd5e0;
|
|
||||||
border-radius: 8px;
|
|
||||||
font-weight: 600;
|
|
||||||
padding: 10px 20px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-cancel-edit:hover {
|
|
||||||
background: #edf2f7;
|
|
||||||
color: #4a5568;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
<div class="container-fluid py-4">
|
<div class="container-fluid py-4">
|
||||||
|
|
||||||
{{-- SUCCESS / ERROR MESSAGES --}}
|
{{-- SUCCESS / ERROR MESSAGES --}}
|
||||||
@@ -1420,7 +1228,6 @@
|
|||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<th>Date</th>
|
<th>Date</th>
|
||||||
<th>Action</th>
|
<th>Action</th>
|
||||||
<th>View</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
@@ -1433,15 +1240,16 @@
|
|||||||
{{-- REVERSE INDEX: सर्वात वरच्या shipment ला सर्वात मोठा क्रमांक --}}
|
{{-- REVERSE INDEX: सर्वात वरच्या shipment ला सर्वात मोठा क्रमांक --}}
|
||||||
<td class="fw-bold">{{ $totalShipments - $loop->index }}</td>
|
<td class="fw-bold">{{ $totalShipments - $loop->index }}</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="#" class="text-primary fw-bold" onclick="openShipmentDetails({{ $ship->id }})">
|
<a href="#" class="text-primary fw-bold"
|
||||||
|
onclick="openShipmentDetails({{ $ship->id }})">
|
||||||
{{ $ship->shipment_id }}
|
{{ $ship->shipment_id }}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ $ship->origin }}</td>
|
<td>{{ $ship->origin }}</td>
|
||||||
<td>{{ $ship->destination }}</td>
|
<td>{{ $ship->destination }}</td>
|
||||||
<td>{{ $ship->total_qty }}</td>
|
<td><span class="badge bg-light text-dark">{{ $ship->total_qty }}</span></td>
|
||||||
<td>{{ $ship->total_kg }} kg</td>
|
<td><span class="badge bg-light text-dark">{{ $ship->total_kg }} kg</span></td>
|
||||||
<td>{{ $ship->total_cbm }} CBM</td>
|
<td><span class="badge bg-light text-dark">{{ $ship->total_cbm }} CBM</span></td>
|
||||||
<td class="fw-bold text-success">₹{{ number_format($ship->total_amount, 2) }}</td>
|
<td class="fw-bold text-success">₹{{ number_format($ship->total_amount, 2) }}</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="badge badge-{{ $ship->status }}">
|
<span class="badge badge-{{ $ship->status }}">
|
||||||
@@ -1478,12 +1286,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
|
||||||
<a href="{{ route('admin.shipments.view', ['id' => $ship->id, 'mode' => 'edit']) }}"
|
|
||||||
class="btn btn-view">
|
|
||||||
<i class="bi bi-eye"></i>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr>
|
||||||
@@ -1521,8 +1323,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ============================= -->
|
<!-- ============================= -->
|
||||||
<!-- SHIPMENT DETAILS MODAL -->
|
<!-- SHIPMENT DETAILS MODAL -->
|
||||||
<!-- ============================= -->
|
<!-- ============================= -->
|
||||||
@@ -1546,6 +1346,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- ========================= -->
|
<!-- ========================= -->
|
||||||
<!-- MODAL LOAD SCRIPT (AJAX) -->
|
<!-- MODAL LOAD SCRIPT (AJAX) -->
|
||||||
<!-- ========================= -->
|
<!-- ========================= -->
|
||||||
@@ -1775,19 +1577,11 @@ function renderTable() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
|
||||||
<a href="/admin/shipments/view/${shipment.id}?mode=edit"
|
|
||||||
class="btn btn-view"
|
|
||||||
title="Edit Shipment">
|
|
||||||
<i class="bi bi-eye"></i>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
`;
|
`;
|
||||||
tbody.appendChild(row);
|
tbody.appendChild(row);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to open shipment details modal
|
|
||||||
function openShipmentDetails(id) {
|
function openShipmentDetails(id) {
|
||||||
let modal = new bootstrap.Modal(document.getElementById('shipmentDetailsModal'));
|
let modal = new bootstrap.Modal(document.getElementById('shipmentDetailsModal'));
|
||||||
let content = document.getElementById('shipmentDetailsContent');
|
let content = document.getElementById('shipmentDetailsContent');
|
||||||
@@ -1958,15 +1752,11 @@ function toggleStatusDropdown(button, shipmentId) {
|
|||||||
|
|
||||||
// Close dropdown when clicking outside
|
// Close dropdown when clicking outside
|
||||||
document.addEventListener('click', function closeDropdown(e) {
|
document.addEventListener('click', function closeDropdown(e) {
|
||||||
// allow clicking links normally
|
|
||||||
if (e.target.closest('a')) return;
|
|
||||||
|
|
||||||
if (!button.contains(e.target) && !dropdown.contains(e.target)) {
|
if (!button.contains(e.target) && !dropdown.contains(e.target)) {
|
||||||
dropdown.classList.remove('show');
|
dropdown.classList.remove('show');
|
||||||
document.removeEventListener('click', closeDropdown);
|
document.removeEventListener('click', closeDropdown);
|
||||||
}
|
}
|
||||||
}, { once: true });
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto-close dropdown after form submission
|
// Auto-close dropdown after form submission
|
||||||
|
|||||||
@@ -150,45 +150,31 @@ Route::prefix('admin')
|
|||||||
// ---------------------------
|
// ---------------------------
|
||||||
// SHIPMENTS (FIXED ROUTES)
|
// SHIPMENTS (FIXED ROUTES)
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
|
|
||||||
// View shipment MUST be before /shipments/{id}
|
|
||||||
Route::get('/shipments/view/{id}', [ShipmentController::class, 'show'])
|
|
||||||
->name('admin.shipments.view');
|
|
||||||
|
|
||||||
// List shipments
|
|
||||||
Route::get('/shipments', [ShipmentController::class, 'index'])
|
Route::get('/shipments', [ShipmentController::class, 'index'])
|
||||||
->name('admin.shipments');
|
->name('admin.shipments');
|
||||||
|
|
||||||
// Create shipment
|
|
||||||
Route::post('/shipments', [ShipmentController::class, 'store'])
|
Route::post('/shipments', [ShipmentController::class, 'store'])
|
||||||
->name('admin.shipments.store');
|
->name('admin.shipments.store');
|
||||||
|
|
||||||
// Update status
|
|
||||||
Route::post('/shipments/update-status', [ShipmentController::class, 'updateStatus'])
|
Route::post('/shipments/update-status', [ShipmentController::class, 'updateStatus'])
|
||||||
->name('admin.shipments.updateStatus');
|
->name('admin.shipments.updateStatus');
|
||||||
|
|
||||||
// Shipment orders (AJAX)
|
// Get shipment orders for modal (AJAX)
|
||||||
Route::get('/shipments/{id}/orders', [ShipmentController::class, 'getShipmentOrders'])
|
Route::get('/shipments/{id}/orders', [ShipmentController::class, 'getShipmentOrders'])
|
||||||
->name('admin.shipments.orders');
|
->name('admin.shipments.orders');
|
||||||
|
|
||||||
// Shipment update
|
// Get shipment details for edit (AJAX)
|
||||||
|
Route::get('/shipments/{id}', [ShipmentController::class, 'show'])
|
||||||
|
->name('admin.shipments.show');
|
||||||
|
|
||||||
|
// Shipment Update
|
||||||
Route::put('/shipments/{id}', [ShipmentController::class, 'update'])
|
Route::put('/shipments/{id}', [ShipmentController::class, 'update'])
|
||||||
->name('admin.shipments.update');
|
->name('admin.shipments.update');
|
||||||
|
|
||||||
// Shipment delete
|
// Shipment Delete
|
||||||
Route::delete('/shipments/{id}', [ShipmentController::class, 'destroy'])
|
Route::delete('/shipments/{id}', [ShipmentController::class, 'destroy'])
|
||||||
->name('admin.shipments.destroy');
|
->name('admin.shipments.destroy');
|
||||||
|
|
||||||
// Remove order
|
|
||||||
Route::post('/shipments/remove-order', [ShipmentController::class, 'removeOrder'])
|
|
||||||
->name('admin.shipments.removeOrder');
|
|
||||||
|
|
||||||
Route::post('/shipments/add-order', [ShipmentController::class, 'addOrder'])
|
|
||||||
->name('admin.shipments.addOrder');
|
|
||||||
|
|
||||||
Route::post('/shipments/{id}/add-orders', [ShipmentController::class, 'addOrders'])
|
|
||||||
->name('admin.shipments.addOrders');
|
|
||||||
|
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
// INVOICES
|
// INVOICES
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
@@ -301,6 +287,11 @@ Route::prefix('admin')
|
|||||||
Route::get('/admin/orders/download/excel', [AdminOrderController::class, 'downloadExcel'])
|
Route::get('/admin/orders/download/excel', [AdminOrderController::class, 'downloadExcel'])
|
||||||
->name('admin.orders.download.excel');
|
->name('admin.orders.download.excel');
|
||||||
|
|
||||||
|
|
||||||
|
Route::prefix('admin/account')->middleware('auth:admin')->name('admin.account.')->group(function () {
|
||||||
|
Route::post('/toggle-payment', [AdminAccountController::class, 'togglePayment'])->name('toggle');
|
||||||
|
});
|
||||||
|
|
||||||
//---------------------------
|
//---------------------------
|
||||||
//Edit Button Route
|
//Edit Button Route
|
||||||
//---------------------------
|
//---------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user