Merge branch 'dev' of http://103.248.30.24:3000/kent-logistics/Kent-logistics-Laravel into dev
This commit is contained in:
@@ -92,7 +92,7 @@ class AdminOrderController extends Controller
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
//If you want to auto-create an invoice at order creation, uncomment:
|
//If you want to auto-create an invoice at order creation, uncomment:
|
||||||
// $this->createInvoice($order);
|
$this->createInvoice($order);
|
||||||
|
|
||||||
return redirect()->route('admin.orders.show', $order->id)
|
return redirect()->route('admin.orders.show', $order->id)
|
||||||
->with('success', 'Order created successfully.');
|
->with('success', 'Order created successfully.');
|
||||||
@@ -500,9 +500,14 @@ public function addTempItem(Request $request)
|
|||||||
session()->push('temp_order_items', $item);
|
session()->push('temp_order_items', $item);
|
||||||
|
|
||||||
return redirect()->to(route('admin.orders.index') . '#createOrderForm')
|
return redirect()->to(route('admin.orders.index') . '#createOrderForm')
|
||||||
|
|
||||||
->with('success', 'Item added.');
|
->with('success', 'Item added.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// STEP 3 : FINISH ORDER
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
public function finishOrder(Request $request)
|
public function finishOrder(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
@@ -518,7 +523,9 @@ public function finishOrder(Request $request)
|
|||||||
->with('error', 'Add at least one item before finishing.');
|
->with('error', 'Add at least one item before finishing.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate Order ID
|
// =======================
|
||||||
|
// GENERATE ORDER ID
|
||||||
|
// =======================
|
||||||
$year = date('y');
|
$year = date('y');
|
||||||
$prefix = "KNT-$year-";
|
$prefix = "KNT-$year-";
|
||||||
|
|
||||||
@@ -527,7 +534,9 @@ public function finishOrder(Request $request)
|
|||||||
|
|
||||||
$orderId = $prefix . str_pad($nextNumber, 8, '0', STR_PAD_LEFT);
|
$orderId = $prefix . str_pad($nextNumber, 8, '0', STR_PAD_LEFT);
|
||||||
|
|
||||||
|
// =======================
|
||||||
// TOTAL SUMS
|
// TOTAL SUMS
|
||||||
|
// =======================
|
||||||
$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'));
|
||||||
$total_ttl_qty = array_sum(array_column($items, 'ttl_qty'));
|
$total_ttl_qty = array_sum(array_column($items, 'ttl_qty'));
|
||||||
@@ -537,7 +546,9 @@ public function finishOrder(Request $request)
|
|||||||
$total_kg = array_sum(array_column($items, 'kg'));
|
$total_kg = array_sum(array_column($items, 'kg'));
|
||||||
$total_ttl_kg = array_sum(array_column($items, 'ttl_kg'));
|
$total_ttl_kg = array_sum(array_column($items, 'ttl_kg'));
|
||||||
|
|
||||||
|
// =======================
|
||||||
// CREATE ORDER
|
// CREATE ORDER
|
||||||
|
// =======================
|
||||||
$order = Order::create([
|
$order = Order::create([
|
||||||
'order_id' => $orderId,
|
'order_id' => $orderId,
|
||||||
'mark_no' => $request->mark_no,
|
'mark_no' => $request->mark_no,
|
||||||
@@ -554,7 +565,7 @@ public function finishOrder(Request $request)
|
|||||||
'status' => 'pending',
|
'status' => 'pending',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// SAVE ALL SUB-ITEMS
|
// SAVE ORDER ITEMS
|
||||||
foreach ($items as $item) {
|
foreach ($items as $item) {
|
||||||
OrderItem::create([
|
OrderItem::create([
|
||||||
'order_id' => $order->id,
|
'order_id' => $order->id,
|
||||||
@@ -573,11 +584,109 @@ public function finishOrder(Request $request)
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =======================
|
||||||
|
// INVOICE CREATION START
|
||||||
|
// =======================
|
||||||
|
|
||||||
|
// 1. Auto-generate invoice number
|
||||||
|
$lastInvoice = \App\Models\Invoice::latest()->first();
|
||||||
|
$nextInvoice = $lastInvoice ? $lastInvoice->id + 1 : 1;
|
||||||
|
$invoiceNumber = 'INV-' . date('Y') . '-' . str_pad($nextInvoice, 6, '0', STR_PAD_LEFT);
|
||||||
|
|
||||||
|
// 2. Fetch customer (using mark list → customer_id)
|
||||||
|
$markList = MarkList::where('mark_no', $order->mark_no)->first();
|
||||||
|
$customer = null;
|
||||||
|
|
||||||
|
if ($markList && $markList->customer_id) {
|
||||||
|
$customer = \App\Models\User::where('customer_id', $markList->customer_id)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Create Invoice Record
|
||||||
|
$invoice = \App\Models\Invoice::create([
|
||||||
|
'order_id' => $order->id,
|
||||||
|
'customer_id' => $customer->id ?? null,
|
||||||
|
'mark_no' => $order->mark_no,
|
||||||
|
|
||||||
|
'invoice_number' => $invoiceNumber,
|
||||||
|
'invoice_date' => now(),
|
||||||
|
'due_date' => now()->addDays(10),
|
||||||
|
|
||||||
|
'payment_method' => null,
|
||||||
|
'reference_no' => null,
|
||||||
|
'status' => 'pending',
|
||||||
|
|
||||||
|
'final_amount' => $total_amount,
|
||||||
|
'gst_percent' => 0,
|
||||||
|
'gst_amount' => 0,
|
||||||
|
'final_amount_with_gst' => $total_amount,
|
||||||
|
|
||||||
|
// snapshot customer fields
|
||||||
|
'customer_name' => $customer->customer_name ?? null,
|
||||||
|
'company_name' => $customer->company_name ?? null,
|
||||||
|
'customer_email' => $customer->email ?? null,
|
||||||
|
'customer_mobile' => $customer->mobile_no ?? null,
|
||||||
|
'customer_address' => $customer->address ?? null,
|
||||||
|
'pincode' => $customer->pincode ?? null,
|
||||||
|
|
||||||
|
'notes' => null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 4. Clone order items into invoice_items
|
||||||
|
foreach ($order->items as $item) {
|
||||||
|
\App\Models\InvoiceItem::create([
|
||||||
|
'invoice_id' => $invoice->id,
|
||||||
|
'description' => $item->description,
|
||||||
|
'ctn' => $item->ctn,
|
||||||
|
'qty' => $item->qty,
|
||||||
|
'ttl_qty' => $item->ttl_qty,
|
||||||
|
'unit' => $item->unit,
|
||||||
|
'price' => $item->price,
|
||||||
|
'ttl_amount' => $item->ttl_amount,
|
||||||
|
'cbm' => $item->cbm,
|
||||||
|
'ttl_cbm' => $item->ttl_cbm,
|
||||||
|
'kg' => $item->kg,
|
||||||
|
'ttl_kg' => $item->ttl_kg,
|
||||||
|
'shop_no' => $item->shop_no,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. TODO: PDF generation (I will add this later)
|
||||||
|
$invoice->pdf_path = null; // placeholder for now
|
||||||
|
$invoice->save();
|
||||||
|
|
||||||
|
// =======================
|
||||||
|
// END INVOICE CREATION
|
||||||
|
// =======================
|
||||||
|
|
||||||
// CLEAR TEMP DATA
|
// CLEAR TEMP DATA
|
||||||
session()->forget(['temp_order_items', 'mark_no', 'origin', 'destination']);
|
session()->forget(['temp_order_items', 'mark_no', 'origin', 'destination']);
|
||||||
|
|
||||||
return redirect()->route('admin.orders.index')
|
return redirect()->route('admin.orders.index')
|
||||||
->with('success', 'Order saved successfully.');
|
->with('success', 'Order + Invoice created successfully.');
|
||||||
|
}
|
||||||
|
// ---------------------------
|
||||||
|
// ORDER CRUD: update / destroy
|
||||||
|
// ---------------------------
|
||||||
|
public function updateItem(Request $request, $id)
|
||||||
|
{
|
||||||
|
$item = OrderItem::findOrFail($id);
|
||||||
|
|
||||||
|
$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,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return back()->with('success', 'Item updated successfully!');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
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;
|
||||||
@@ -106,6 +107,9 @@ 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,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -113,22 +117,110 @@ 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)
|
||||||
{
|
{
|
||||||
$shipment = Shipment::findOrFail($id);
|
$mode = request()->get('mode', 'view');
|
||||||
|
|
||||||
// Load full order data from orders table
|
$shipment = Shipment::with(['items.order'])->findOrFail($id);
|
||||||
$orders = Order::whereIn('id',
|
|
||||||
ShipmentItem::where('shipment_id', $id)->pluck('order_id')
|
// Get orders from shipment items
|
||||||
)->get();
|
$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);
|
||||||
|
$orderIds = $request->order_ids;
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$orders = Order::whereIn('id', $orderIds)->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' => $orders
|
'orders' => $addedOrders
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Failed to add orders: ' . $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -209,4 +301,77 @@ 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
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -87,8 +87,22 @@ class UserProfileController extends Controller
|
|||||||
return response()->json([
|
return response()->json([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => 'Profile image updated successfully',
|
'message' => 'Profile image updated successfully',
|
||||||
|
'data' => [
|
||||||
|
'customer_id' => $user->customer_id,
|
||||||
|
'customer_name' => $user->customer_name,
|
||||||
|
'company_name' => $user->company_name,
|
||||||
|
'designation' => $user->designation,
|
||||||
|
'email' => $user->email,
|
||||||
|
'mobile' => $user->mobile_no,
|
||||||
|
'address' => $user->address,
|
||||||
|
'pincode' => $user->pincode,
|
||||||
|
'status' => $user->status,
|
||||||
|
'customer_type' => $user->customer_type,
|
||||||
'profile_image' => url($user->profile_image),
|
'profile_image' => url($user->profile_image),
|
||||||
|
'date' => $user->date,
|
||||||
|
]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,11 +12,26 @@ class ShipmentItem extends Model
|
|||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'shipment_id',
|
'shipment_id',
|
||||||
'order_id',
|
'order_id',
|
||||||
|
|
||||||
|
// OLD fields (keep them if old data exists)
|
||||||
'order_ctn',
|
'order_ctn',
|
||||||
'order_qty',
|
'order_qty',
|
||||||
'order_ttl_qty',
|
'order_ttl_qty',
|
||||||
'order_ttl_amount',
|
'order_ttl_amount',
|
||||||
'order_ttl_kg',
|
'order_ttl_kg',
|
||||||
|
|
||||||
|
// NEW fields (added for correct shipments)
|
||||||
|
'ctn',
|
||||||
|
'qty',
|
||||||
|
'ttl_qty',
|
||||||
|
|
||||||
|
'cbm',
|
||||||
|
'ttl_cbm',
|
||||||
|
|
||||||
|
'kg',
|
||||||
|
'ttl_kg',
|
||||||
|
|
||||||
|
'ttl_amount',
|
||||||
];
|
];
|
||||||
|
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
@@ -36,11 +51,11 @@ class ShipmentItem extends Model
|
|||||||
// Helper: return order data with fallback to snapshot
|
// Helper: return order data with fallback to snapshot
|
||||||
public function getDisplayQty()
|
public function getDisplayQty()
|
||||||
{
|
{
|
||||||
return $this->order->qty ?? $this->order_qty;
|
return $this->qty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDisplayAmount()
|
public function getDisplayAmount()
|
||||||
{
|
{
|
||||||
return $this->order->ttl_amount ?? $this->order_ttl_amount;
|
return $this->ttl_amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
689
composer.lock
generated
689
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('shipment_items', function (Blueprint $table) {
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'ctn')) {
|
||||||
|
$table->integer('ctn')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'qty')) {
|
||||||
|
$table->integer('qty')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'ttl_qty')) {
|
||||||
|
$table->integer('ttl_qty')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'cbm')) {
|
||||||
|
$table->double('cbm')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'ttl_cbm')) {
|
||||||
|
$table->double('ttl_cbm')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'kg')) {
|
||||||
|
$table->double('kg')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'ttl_kg')) {
|
||||||
|
$table->double('ttl_kg')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('shipment_items', 'ttl_amount')) {
|
||||||
|
$table->double('ttl_amount')->default(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('shipment_items', function (Blueprint $table) {
|
||||||
|
// safely remove columns (optional)
|
||||||
|
$columns = [
|
||||||
|
'ctn', 'qty', 'ttl_qty', 'cbm',
|
||||||
|
'ttl_cbm', 'kg', 'ttl_kg', 'ttl_amount'
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($columns as $col) {
|
||||||
|
if (Schema::hasColumn('shipment_items', $col)) {
|
||||||
|
$table->dropColumn($col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000028.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000028.pdf
Normal file
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000029.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000029.pdf
Normal file
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000030.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000030.pdf
Normal file
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000032.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000032.pdf
Normal file
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000033.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000033.pdf
Normal file
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 65 KiB |
BIN
public/profile_upload/profile_1764743106.jpg
Normal file
BIN
public/profile_upload/profile_1764743106.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 209 KiB |
@@ -15,27 +15,30 @@
|
|||||||
<h4 class="fw-bold mb-0">Order Details</h4>
|
<h4 class="fw-bold mb-0">Order Details</h4>
|
||||||
<small class="text-muted">Detailed view of this shipment order</small>
|
<small class="text-muted">Detailed view of this shipment order</small>
|
||||||
</div>
|
</div>
|
||||||
<a href="{{ route('admin.dashboard') }}" class="btn-close"></a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- ACTION BUTTONS --}}
|
|
||||||
<div class="mt-3 d-flex gap-2">
|
|
||||||
|
|
||||||
{{-- ADD ITEM --}}
|
{{-- ADD ITEM --}}
|
||||||
<button class="btn btn-add-item" data-bs-toggle="modal" data-bs-target="#addItemModal">
|
<button class="btn btn-add-item" data-bs-toggle="modal" data-bs-target="#addItemModal">
|
||||||
<i class="fas fa-plus-circle me-2"></i>Add New Item
|
<i class="fas fa-plus-circle me-2"></i>Add New Item
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{{-- EDIT ORDER --}}
|
<a href="{{ route('admin.dashboard') }}" class="btn-close"></a>
|
||||||
@if($order->status === 'pending')
|
</div>
|
||||||
|
|
||||||
|
<!-- {{-- ACTION BUTTONS --}}
|
||||||
|
<div class="mt-3 d-flex gap-2">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{{-- EDIT ORDER --}} -->
|
||||||
|
<!-- @if($order->status === 'pending')
|
||||||
<button class="btn btn-edit-order" onclick="document.getElementById('editOrderForm').style.display='block'">
|
<button class="btn btn-edit-order" onclick="document.getElementById('editOrderForm').style.display='block'">
|
||||||
<i class="fas fa-edit me-2"></i>Edit Order
|
<i class="fas fa-edit me-2"></i>Edit Order
|
||||||
</button>
|
</button>
|
||||||
@else
|
@else
|
||||||
<button class="btn btn-edit-order" disabled><i class="fas fa-edit me-2"></i>Edit Order</button>
|
<button class="btn btn-edit-order" disabled><i class="fas fa-edit me-2"></i>Edit Order</button>
|
||||||
@endif
|
@endif -->
|
||||||
|
|
||||||
{{-- DELETE ORDER --}}
|
<!-- {{-- DELETE ORDER --}}
|
||||||
@if($order->status === 'pending')
|
@if($order->status === 'pending')
|
||||||
<form action="{{ route('admin.orders.destroy', $order->id) }}"
|
<form action="{{ route('admin.orders.destroy', $order->id) }}"
|
||||||
method="POST"
|
method="POST"
|
||||||
@@ -46,9 +49,9 @@
|
|||||||
<i class="fas fa-trash-alt me-2"></i>Delete Order
|
<i class="fas fa-trash-alt me-2"></i>Delete Order
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
@endif
|
@endif -->
|
||||||
|
|
||||||
</div>
|
<!-- </div> -->
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
@@ -56,7 +59,7 @@
|
|||||||
<div id="editOrderForm" class="p-3 bg-light rounded mb-4 shadow-sm" style="display:none;">
|
<div id="editOrderForm" class="p-3 bg-light rounded mb-4 shadow-sm" style="display:none;">
|
||||||
<h5 class="fw-bold mb-3">Edit Order</h5>
|
<h5 class="fw-bold mb-3">Edit Order</h5>
|
||||||
|
|
||||||
<form action="{{ route('admin.orders.update', $order->id) }}" method="POST">
|
<form action="{{ route('admin.orders.updateItem', $order->id) }}" method="POST">
|
||||||
@csrf
|
@csrf
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -185,7 +188,18 @@
|
|||||||
<td>{{ $item->ttl_kg }}</td>
|
<td>{{ $item->ttl_kg }}</td>
|
||||||
<td>{{ $item->shop_no }}</td>
|
<td>{{ $item->shop_no }}</td>
|
||||||
|
|
||||||
<td>
|
<td class="d-flex justify-content-center gap-2">
|
||||||
|
|
||||||
|
{{-- EDIT BUTTON --}}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-sm btn-edit-item"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#editItemModal{{ $item->id }}">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{{-- DELETE BUTTON --}}
|
||||||
<form action="{{ route('admin.orders.deleteItem', $item->id) }}"
|
<form action="{{ route('admin.orders.deleteItem', $item->id) }}"
|
||||||
method="POST"
|
method="POST"
|
||||||
onsubmit="return confirm('Delete this item?')">
|
onsubmit="return confirm('Delete this item?')">
|
||||||
@@ -196,12 +210,135 @@
|
|||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@foreach($order->items as $item)
|
||||||
|
<div class="modal fade" id="editItemModal{{ $item->id }}" tabindex="-1">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content custom-modal">
|
||||||
|
|
||||||
|
<div class="modal-header modal-gradient-header">
|
||||||
|
<h5 class="modal-title text-white">
|
||||||
|
<i class="fas fa-edit me-2"></i>Edit Item
|
||||||
|
</h5>
|
||||||
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form action="{{ route('admin.orders.updateItem', $item->id) }}" method="POST">
|
||||||
|
@csrf
|
||||||
|
@method('PUT')
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Description</label>
|
||||||
|
<input type="text" name="description"
|
||||||
|
value="{{ $item->description }}"
|
||||||
|
class="form-control custom-input" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">CTN</label>
|
||||||
|
<input type="number" name="ctn"
|
||||||
|
value="{{ $item->ctn }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">QTY</label>
|
||||||
|
<input type="number" name="qty"
|
||||||
|
value="{{ $item->qty }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">TTL QTY</label>
|
||||||
|
<input type="number" name="ttl_qty"
|
||||||
|
value="{{ $item->ttl_qty }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">Unit</label>
|
||||||
|
<input type="text" name="unit"
|
||||||
|
value="{{ $item->unit }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">Price</label>
|
||||||
|
<input type="number" name="price"
|
||||||
|
value="{{ $item->price }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">Total Amount</label>
|
||||||
|
<input type="number" name="ttl_amount"
|
||||||
|
value="{{ $item->ttl_amount }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">CBM</label>
|
||||||
|
<input type="number" name="cbm"
|
||||||
|
value="{{ $item->cbm }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">TTL CBM</label>
|
||||||
|
<input type="number" name="ttl_cbm"
|
||||||
|
value="{{ $item->ttl_cbm }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">KG</label>
|
||||||
|
<input type="number" name="kg"
|
||||||
|
value="{{ $item->kg }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">TTL KG</label>
|
||||||
|
<input type="number" name="ttl_kg"
|
||||||
|
value="{{ $item->ttl_kg }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3">
|
||||||
|
<label class="form-label">Shop No</label>
|
||||||
|
<input type="text" name="shop_no"
|
||||||
|
value="{{ $item->shop_no }}"
|
||||||
|
class="form-control custom-input">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-modal-close" data-bs-dismiss="modal">Close</button>
|
||||||
|
<button type="submit" class="btn btn-modal-add">Add Item</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
|
||||||
{{-- TOTALS --}}
|
{{-- TOTALS --}}
|
||||||
<div class="row text-center mt-4">
|
<div class="row text-center mt-4">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
@@ -239,7 +376,7 @@
|
|||||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form action="{{ route('admin.orders.addItem', $order->id) }}" method="POST">
|
<form id="addItemForm" action="{{ route('admin.orders.addItem', $order->id) }}" method="POST">
|
||||||
@csrf
|
@csrf
|
||||||
|
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
@@ -253,54 +390,75 @@
|
|||||||
|
|
||||||
<h5 class="section-title">Deleted Items (Use / Restore)</h5>
|
<h5 class="section-title">Deleted Items (Use / Restore)</h5>
|
||||||
|
|
||||||
<ul class="list-group mb-3">
|
<div class="table-responsive mb-4">
|
||||||
|
<table class="table table-bordered align-middle text-center">
|
||||||
|
<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>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
@forelse($deletedItems as $deleted)
|
<tbody>
|
||||||
<li class="list-group-item">
|
@forelse($deletedItems as $key => $deleted)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $key + 1 }}</td>
|
||||||
|
<td>{{ $deleted->description }}</td>
|
||||||
|
<td>{{ $deleted->ctn }}</td>
|
||||||
|
<td>{{ $deleted->qty }}</td>
|
||||||
|
<td>{{ $deleted->ttl_qty }}</td>
|
||||||
|
<td>{{ $deleted->unit }}</td>
|
||||||
|
<td>{{ number_format($deleted->price, 2) }}</td>
|
||||||
|
<td>{{ number_format($deleted->ttl_amount, 2) }}</td>
|
||||||
|
<td>{{ $deleted->cbm }}</td>
|
||||||
|
<td>{{ $deleted->ttl_cbm }}</td>
|
||||||
|
<td>{{ $deleted->kg }}</td>
|
||||||
|
<td>{{ $deleted->ttl_kg }}</td>
|
||||||
|
<td>{{ $deleted->shop_no }}</td>
|
||||||
|
|
||||||
<div class="d-flex justify-content-between">
|
<td class="d-flex justify-content-center gap-2">
|
||||||
|
|
||||||
<div>
|
{{-- USE THIS ITEM --}}
|
||||||
<strong>{{ $deleted->description }}</strong><br>
|
<button type="button"
|
||||||
<small>
|
class="btn btn-sm btn-use-item"
|
||||||
CTN: {{ $deleted->ctn }},
|
|
||||||
QTY: {{ $deleted->qty }},
|
|
||||||
TTL/QTY: {{ $deleted->ttl_qty }},
|
|
||||||
Unit: {{ $deleted->unit }},
|
|
||||||
Price: ₹{{ $deleted->price }},
|
|
||||||
TTL Amt: ₹{{ $deleted->ttl_amount }},
|
|
||||||
CBM: {{ $deleted->cbm }},
|
|
||||||
TTL CBM: {{ $deleted->ttl_cbm }},
|
|
||||||
KG: {{ $deleted->kg }},
|
|
||||||
TTL KG: {{ $deleted->ttl_kg }},
|
|
||||||
Shop: {{ $deleted->shop_no }}
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="d-flex gap-2">
|
|
||||||
|
|
||||||
{{-- Auto-fill button --}}
|
|
||||||
<button type="button" class="btn btn-sm btn-use-item"
|
|
||||||
onclick="fillFormFromDeleted({{ json_encode($deleted) }})">
|
onclick="fillFormFromDeleted({{ json_encode($deleted) }})">
|
||||||
Use This
|
Use
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{{-- Restore --}}
|
{{-- RESTORE ITEM --}}
|
||||||
<form action="{{ route('admin.orders.restoreItem', $deleted->id) }}" method="POST">
|
<form action="{{ route('admin.orders.restoreItem', $deleted->id) }}" method="POST">
|
||||||
@csrf
|
@csrf
|
||||||
<button class="btn btn-sm btn-restore">Restore</button>
|
<button type="button"
|
||||||
|
class="btn btn-sm btn-restore js-restore-item"
|
||||||
|
data-id="{{ $deleted->id }}"
|
||||||
|
data-url="{{ route('admin.orders.restoreItem', $deleted->id) }}">
|
||||||
|
Restore
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</div>
|
</td>
|
||||||
|
</tr>
|
||||||
</div>
|
|
||||||
|
|
||||||
</li>
|
|
||||||
@empty
|
@empty
|
||||||
<li class="list-group-item text-muted">No deleted items.</li>
|
<tr>
|
||||||
|
<td colspan="14" class="text-muted">No deleted items.</td>
|
||||||
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
{{-- ADD FORM --}}
|
{{-- ADD FORM --}}
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
@@ -380,21 +538,62 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
const token = '{{ csrf_token() }}';
|
||||||
|
|
||||||
|
document.querySelectorAll('.js-restore-item').forEach(function (btn) {
|
||||||
|
btn.addEventListener('click', function () {
|
||||||
|
if (!confirm('Restore this item?')) return;
|
||||||
|
|
||||||
|
const url = this.dataset.url;
|
||||||
|
const row = this.closest('tr');
|
||||||
|
|
||||||
|
fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'X-CSRF-TOKEN': token,
|
||||||
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({})
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) throw new Error('Restore failed');
|
||||||
|
return response.json().catch(() => ({}));
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
row.remove();
|
||||||
|
location.reload(); // 🔥 refresh UI so restored item appears
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
alert('Could not restore item. Please try again.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
{{-- AUTO-FILL SCRIPT --}}
|
{{-- AUTO-FILL SCRIPT --}}
|
||||||
<script>
|
<script>
|
||||||
function fillFormFromDeleted(item) {
|
function fillFormFromDeleted(item) {
|
||||||
document.querySelector('input[name="description"]').value = item.description;
|
let form = document.getElementById('addItemForm');
|
||||||
document.querySelector('input[name="ctn"]').value = item.ctn;
|
|
||||||
document.querySelector('input[name="qty"]').value = item.qty;
|
form.querySelector('input[name="description"]').value = item.description;
|
||||||
document.querySelector('input[name="ttl_qty"]').value = item.ttl_qty;
|
form.querySelector('input[name="ctn"]').value = item.ctn;
|
||||||
document.querySelector('input[name="unit"]').value = item.unit;
|
form.querySelector('input[name="qty"]').value = item.qty;
|
||||||
document.querySelector('input[name="price"]').value = item.price;
|
form.querySelector('input[name="ttl_qty"]').value = item.ttl_qty;
|
||||||
document.querySelector('input[name="ttl_amount"]').value = item.ttl_amount;
|
form.querySelector('input[name="unit"]').value = item.unit;
|
||||||
document.querySelector('input[name="cbm"]').value = item.cbm;
|
form.querySelector('input[name="price"]').value = item.price;
|
||||||
document.querySelector('input[name="ttl_cbm"]').value = item.ttl_cbm;
|
form.querySelector('input[name="ttl_amount"]').value = item.ttl_amount;
|
||||||
document.querySelector('input[name="kg"]').value = item.kg;
|
form.querySelector('input[name="cbm"]').value = item.cbm;
|
||||||
document.querySelector('input[name="ttl_kg"]').value = item.ttl_kg;
|
form.querySelector('input[name="ttl_cbm"]').value = item.ttl_cbm;
|
||||||
document.querySelector('input[name="shop_no"]').value = item.shop_no;
|
form.querySelector('input[name="kg"]').value = item.kg;
|
||||||
|
form.querySelector('input[name="ttl_kg"]').value = item.ttl_kg;
|
||||||
|
form.querySelector('input[name="shop_no"]').value = item.shop_no;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -404,13 +603,15 @@ function fillFormFromDeleted(item) {
|
|||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
border: none;
|
border: none;
|
||||||
color: white;
|
color: white;
|
||||||
padding: 12px 24px;
|
padding: 6px 14px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
font-size: 0.85rem;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
box-shadow: 0 4px 15px 0 rgba(102, 126, 234, 0.3);
|
box-shadow: 0 4px 15px 0 rgba(102, 126, 234, 0.3);
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
margin-right: -800px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-add-item:hover {
|
.btn-add-item:hover {
|
||||||
|
|||||||
@@ -63,6 +63,7 @@
|
|||||||
--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;
|
||||||
@@ -89,9 +90,69 @@
|
|||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-shipment-bar > * {
|
.search-input-container:focus-within {
|
||||||
position: relative;
|
border-color: #4361ee;
|
||||||
z-index: 1;
|
box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.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,
|
||||||
@@ -154,6 +215,26 @@
|
|||||||
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 {
|
||||||
@@ -245,7 +326,7 @@
|
|||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* UPDATED: Status Badge Styles - ALL SAME SIZE */
|
/* UPDATED: Status Badge Styles - ALL SAME SIZE WITH ICONS */
|
||||||
.badge {
|
.badge {
|
||||||
padding: 7px 17px !important;
|
padding: 7px 17px !important;
|
||||||
border-radius: 20px !important;
|
border-radius: 20px !important;
|
||||||
@@ -258,7 +339,15 @@
|
|||||||
line-height: 1.2 !important;
|
line-height: 1.2 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pending Status - SAME SIZE */
|
/* Status icons */
|
||||||
|
.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;
|
||||||
@@ -266,7 +355,7 @@
|
|||||||
width: 110px;
|
width: 110px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In Transit Status - SAME SIZE */
|
/* In Transit Status - SAME SIZE WITH TRUCK ICON */
|
||||||
.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;
|
||||||
@@ -274,7 +363,7 @@
|
|||||||
width: 110px;
|
width: 110px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dispatched Status - SAME SIZE */
|
/* Dispatched Status - SAME SIZE WITH BOX ICON */
|
||||||
.badge-dispatched {
|
.badge-dispatched {
|
||||||
background: linear-gradient(135deg, #e9d5ff, #c4b5fd) !important;
|
background: linear-gradient(135deg, #e9d5ff, #c4b5fd) !important;
|
||||||
color: #6b21a8 !important;
|
color: #6b21a8 !important;
|
||||||
@@ -282,7 +371,7 @@
|
|||||||
width: 110px;
|
width: 110px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delivered Status - SAME SIZE */
|
/* Delivered Status - SAME SIZE WITH CHECK ICON */
|
||||||
.badge-delivered {
|
.badge-delivered {
|
||||||
background: linear-gradient(135deg, #d1fae5, #a7f3d0) !important;
|
background: linear-gradient(135deg, #d1fae5, #a7f3d0) !important;
|
||||||
color: #065f46 !important;
|
color: #065f46 !important;
|
||||||
@@ -447,6 +536,66 @@
|
|||||||
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;
|
||||||
@@ -681,6 +830,9 @@
|
|||||||
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 {
|
||||||
@@ -688,7 +840,7 @@
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shipment Details Modal */
|
/* Shipment Details Modal - UPDATED TO MATCH SECOND CODE */
|
||||||
.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;
|
||||||
@@ -778,7 +930,7 @@
|
|||||||
border-bottom-right-radius: 10px;
|
border-bottom-right-radius: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shipment Totals Section */
|
/* Shipment Totals Section - UPDATED */
|
||||||
.shipment-totals {
|
.shipment-totals {
|
||||||
margin-top: 25px;
|
margin-top: 25px;
|
||||||
padding: 25px;
|
padding: 25px;
|
||||||
@@ -1062,8 +1214,48 @@
|
|||||||
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 --}}
|
||||||
@@ -1228,6 +1420,7 @@
|
|||||||
<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>
|
||||||
|
|
||||||
@@ -1240,16 +1433,15 @@
|
|||||||
{{-- 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"
|
<a href="#" class="text-primary fw-bold" onclick="openShipmentDetails({{ $ship->id }})">
|
||||||
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><span class="badge bg-light text-dark">{{ $ship->total_qty }}</span></td>
|
<td>{{ $ship->total_qty }}</td>
|
||||||
<td><span class="badge bg-light text-dark">{{ $ship->total_kg }} kg</span></td>
|
<td>{{ $ship->total_kg }} kg</td>
|
||||||
<td><span class="badge bg-light text-dark">{{ $ship->total_cbm }} CBM</span></td>
|
<td>{{ $ship->total_cbm }} CBM</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 }}">
|
||||||
@@ -1286,6 +1478,12 @@
|
|||||||
</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>
|
||||||
@@ -1323,6 +1521,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- ============================= -->
|
<!-- ============================= -->
|
||||||
<!-- SHIPMENT DETAILS MODAL -->
|
<!-- SHIPMENT DETAILS MODAL -->
|
||||||
<!-- ============================= -->
|
<!-- ============================= -->
|
||||||
@@ -1346,8 +1546,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ========================= -->
|
<!-- ========================= -->
|
||||||
<!-- MODAL LOAD SCRIPT (AJAX) -->
|
<!-- MODAL LOAD SCRIPT (AJAX) -->
|
||||||
<!-- ========================= -->
|
<!-- ========================= -->
|
||||||
@@ -1577,11 +1775,19 @@ 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');
|
||||||
@@ -1752,11 +1958,15 @@ 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
|
||||||
|
|||||||
975
resources/views/admin/view-shipment.blade.php
Normal file
975
resources/views/admin/view-shipment.blade.php
Normal file
@@ -0,0 +1,975 @@
|
|||||||
|
@extends('admin.layouts.app')
|
||||||
|
|
||||||
|
@section('page-title', 'Shipment Details')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* ===== ANIMATIONS ===== */
|
||||||
|
.fade-in {
|
||||||
|
animation: fadeIn 0.6s ease-out;
|
||||||
|
}
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from { opacity: 0; transform: translateY(10px); }
|
||||||
|
to { opacity: 1; transform: translateY(0px); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== CARD STYLES ===== */
|
||||||
|
.card {
|
||||||
|
border-radius: 20px;
|
||||||
|
background: #ffffff;
|
||||||
|
box-shadow: 0 15px 35px rgba(13, 38, 76, 0.08);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||||
|
box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover {
|
||||||
|
transform: translateY(-6px);
|
||||||
|
box-shadow: 0 20px 40px rgba(103, 126, 234, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header h5 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 800;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== GLASSMORPHISM BUTTON ===== */
|
||||||
|
.glass-btn {
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(103, 126, 234, 0.25) 0%,
|
||||||
|
rgba(118, 75, 162, 0.25) 100%
|
||||||
|
);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
-webkit-backdrop-filter: blur(12px);
|
||||||
|
border: 1.5px solid rgba(255, 255, 255, 0.4);
|
||||||
|
color: #ffffff !important;
|
||||||
|
padding: 12px 24px;
|
||||||
|
border-radius: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
box-shadow:
|
||||||
|
0 8px 32px rgba(103, 126, 234, 0.2),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.3),
|
||||||
|
inset 0 -1px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-btn::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(103, 126, 234, 0.4) 0%,
|
||||||
|
rgba(118, 75, 162, 0.4) 100%
|
||||||
|
);
|
||||||
|
z-index: -1;
|
||||||
|
transition: opacity 0.4s ease;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-btn:hover {
|
||||||
|
transform: translateY(-4px) scale(1.05);
|
||||||
|
box-shadow:
|
||||||
|
0 15px 40px rgba(103, 126, 234, 0.35),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.4),
|
||||||
|
inset 0 -1px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
border-color: rgba(255, 255, 255, 0.6);
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(103, 126, 234, 0.15) 0%,
|
||||||
|
rgba(118, 75, 162, 0.15) 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-btn:hover::before {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-btn:active {
|
||||||
|
transform: translateY(-1px) scale(0.98);
|
||||||
|
transition: transform 0.1s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-btn i {
|
||||||
|
font-size: 18px;
|
||||||
|
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== HEADER STYLES ===== */
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16px;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: #fff;
|
||||||
|
padding: 22px 28px;
|
||||||
|
border-radius: 20px 20px 0 0 !important;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: linear-gradient(
|
||||||
|
to right,
|
||||||
|
rgba(255, 255, 255, 0.1) 0%,
|
||||||
|
rgba(255, 255, 255, 0.05) 100%
|
||||||
|
);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-controls {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-cancel-btn {
|
||||||
|
background: rgba(255, 255, 255, 0.15);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
color: rgba(255, 255, 255, 0.95);
|
||||||
|
border: 1.5px solid rgba(255, 255, 255, 0.3);
|
||||||
|
padding: 10px 14px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-cancel-btn:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.25);
|
||||||
|
border-color: rgba(255, 255, 255, 0.5);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== INFO BLOCKS ===== */
|
||||||
|
.shipment-info-box {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 24px;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipment-info-item {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 220px;
|
||||||
|
background: linear-gradient(145deg, #ffffff, #f8fafc);
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow:
|
||||||
|
0 5px 20px rgba(0, 0, 0, 0.05),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
||||||
|
text-align: center;
|
||||||
|
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.8);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipment-info-item::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 4px;
|
||||||
|
background: linear-gradient(90deg, #667eea, #764ba2);
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.4s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipment-info-item:hover {
|
||||||
|
transform: translateY(-6px);
|
||||||
|
box-shadow:
|
||||||
|
0 15px 35px rgba(103, 126, 234, 0.15),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipment-info-item:hover::before {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipment-info-label {
|
||||||
|
color: #64748b;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shipment-info-value {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #1e293b;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== TOTAL BOXES ===== */
|
||||||
|
.total-box {
|
||||||
|
background: linear-gradient(145deg, #ffffff, #f8fafc);
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 16px;
|
||||||
|
box-shadow:
|
||||||
|
0 5px 20px rgba(0, 0, 0, 0.05),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
||||||
|
text-align: center;
|
||||||
|
min-width: 160px;
|
||||||
|
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.8);
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-box::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 3px;
|
||||||
|
background: linear-gradient(90deg, #667eea, #764ba2);
|
||||||
|
transform: translateX(-100%);
|
||||||
|
transition: transform 0.4s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-box:hover {
|
||||||
|
transform: translateY(-5px) scale(1.03);
|
||||||
|
box-shadow:
|
||||||
|
0 15px 35px rgba(103, 126, 234, 0.15),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-box:hover::after {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-title {
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #64748b;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-value {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 900;
|
||||||
|
color: #1e293b;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== TABLE STYLES ===== */
|
||||||
|
.table {
|
||||||
|
border-collapse: separate;
|
||||||
|
border-spacing: 0;
|
||||||
|
border-radius: 16px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #ffffff;
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table thead th {
|
||||||
|
background: #667eea ;
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 18px;
|
||||||
|
white-space: nowrap;
|
||||||
|
border: none;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table thead th::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 15px;
|
||||||
|
right: 15px;
|
||||||
|
height: 1px;
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tbody tr {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-left: 3px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tbody tr:hover {
|
||||||
|
background: linear-gradient(90deg, rgba(103, 126, 234, 0.05), rgba(118, 75, 162, 0.05));
|
||||||
|
transform: translateX(4px);
|
||||||
|
border-left: 3px solid #667eea;
|
||||||
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.table tbody td {
|
||||||
|
padding: 16px;
|
||||||
|
vertical-align: middle;
|
||||||
|
white-space: nowrap;
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== GLASSMORPHISM MODAL ===== */
|
||||||
|
#newOrderModal .modal-content {
|
||||||
|
background: rgba(255, 255, 255, 0.95);
|
||||||
|
backdrop-filter: blur(20px) saturate(180%);
|
||||||
|
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
||||||
|
border-radius: 24px;
|
||||||
|
border: 1.5px solid rgba(255, 255, 255, 0.3);
|
||||||
|
box-shadow:
|
||||||
|
0 25px 50px -12px rgba(0, 0, 0, 0.25),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.5);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .modal-header {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
|
||||||
|
padding: 24px 32px;
|
||||||
|
border-radius: 24px 24px 0 0;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .modal-header::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: linear-gradient(
|
||||||
|
to right,
|
||||||
|
rgba(255, 255, 255, 0.1) 0%,
|
||||||
|
rgba(255, 255, 255, 0.05) 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .modal-title {
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: 800;
|
||||||
|
font-size: 22px;
|
||||||
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .btn-close {
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 8px;
|
||||||
|
opacity: 0.9;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .btn-close:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
opacity: 1;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .modal-body {
|
||||||
|
background: rgba(248, 250, 252, 0.7);
|
||||||
|
padding: 32px;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .modal-footer {
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.4);
|
||||||
|
padding: 24px 32px;
|
||||||
|
border-radius: 0 0 24px 24px;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal h6 {
|
||||||
|
color: #1e293b;
|
||||||
|
font-weight: 700;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
font-size: 16px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== ORDER LIST ITEMS ===== */
|
||||||
|
#availableOrdersList,
|
||||||
|
#deletedOrdersList {
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
border-radius: 16px;
|
||||||
|
background: rgba(255, 255, 255, 0.6);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border: 1.5px solid rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item {
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
border: 1.5px solid rgba(255, 255, 255, 0.4);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
border-radius: 12px !important;
|
||||||
|
padding: 16px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item:hover {
|
||||||
|
background: rgba(103, 126, 234, 0.1);
|
||||||
|
border-color: rgba(103, 126, 234, 0.3);
|
||||||
|
transform: translateX(4px);
|
||||||
|
box-shadow: 0 5px 15px rgba(103, 126, 234, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item strong {
|
||||||
|
color: #1e293b;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item .small {
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-checkbox {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 2px solid #cbd5e1;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-checkbox:checked {
|
||||||
|
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||||
|
border-color: #667eea;
|
||||||
|
box-shadow: 0 0 0 3px rgba(103, 126, 234, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== MODAL BUTTONS ===== */
|
||||||
|
#newOrderModal .btn-secondary {
|
||||||
|
background: rgba(100, 116, 139, 0.2);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border: 1.5px solid rgba(100, 116, 139, 0.3);
|
||||||
|
color: #64748b;
|
||||||
|
padding: 12px 28px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .btn-secondary:hover {
|
||||||
|
background: rgba(100, 116, 139, 0.3);
|
||||||
|
border-color: rgba(100, 116, 139, 0.5);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 6px 20px rgba(100, 116, 139, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .btn-success {
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(34, 197, 94, 0.25) 0%,
|
||||||
|
rgba(21, 128, 61, 0.25) 100%
|
||||||
|
);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
border: 1.5px solid rgba(34, 197, 94, 0.4);
|
||||||
|
color: #166534;
|
||||||
|
padding: 12px 28px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow:
|
||||||
|
0 8px 25px rgba(34, 197, 94, 0.2),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#newOrderModal .btn-success:hover {
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(34, 197, 94, 0.35) 0%,
|
||||||
|
rgba(21, 128, 61, 0.35) 100%
|
||||||
|
);
|
||||||
|
border-color: rgba(34, 197, 94, 0.6);
|
||||||
|
color: #14532d;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow:
|
||||||
|
0 12px 30px rgba(34, 197, 94, 0.3),
|
||||||
|
inset 0 1px 0 rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== SCROLLBAR STYLING ===== */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: rgba(0, 0, 0, 0.05);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: linear-gradient(135deg, #5a6fe8, #6a42a0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== ACTION BUTTONS ===== */
|
||||||
|
.btn-secondary {
|
||||||
|
background: linear-gradient(135deg, #94a3b8, #64748b);
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
padding: 12px 28px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
box-shadow: 0 6px 20px rgba(100, 116, 139, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary:hover {
|
||||||
|
background: linear-gradient(135deg, #8492a6, #565e6e);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 10px 25px rgba(100, 116, 139, 0.3);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===== RESPONSIVE ADJUSTMENTS ===== */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.shipment-info-item,
|
||||||
|
.total-box {
|
||||||
|
min-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-controls {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glass-btn {
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="container-fluid py-4">
|
||||||
|
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="title-row">
|
||||||
|
<h5 class="mb-0"><i class="bi bi-truck me-2"></i>Shipment Details</h5>
|
||||||
|
<!-- <small class="text-white-50" style="margin-left:8px; font-weight:600;">{{ $shipment->shipment_id ?? '' }}</small> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="header-controls">
|
||||||
|
<!-- Add Order button (top-right) with glass effect -->
|
||||||
|
@if($mode === 'edit' && $shipment->status === 'pending')
|
||||||
|
<a href="#" data-bs-toggle="modal" data-bs-target="#newOrderModal" class="glass-btn">
|
||||||
|
<i class="bi bi-plus-circle"></i> Add Order
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<!-- Cancel/close: goes back to shipments list -->
|
||||||
|
<a href="{{ route('admin.shipments') }}" class="btn header-cancel-btn" title="Cancel / Back">
|
||||||
|
<i class="bi bi-x-lg"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<!-- ================================ -->
|
||||||
|
<!-- SHIPMENT MAIN DETAILS -->
|
||||||
|
<!-- ================================ -->
|
||||||
|
<div class="shipment-info-box">
|
||||||
|
|
||||||
|
<div class="shipment-info-item">
|
||||||
|
<div class="shipment-info-label">Shipment ID</div>
|
||||||
|
<div class="shipment-info-value">{{ $shipment->shipment_id }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shipment-info-item">
|
||||||
|
<div class="shipment-info-label">Status</div>
|
||||||
|
<div class="shipment-info-value text-capitalize">
|
||||||
|
{{ str_replace('_', ' ', $shipment->status) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shipment-info-item">
|
||||||
|
<div class="shipment-info-label">Shipment Date</div>
|
||||||
|
<div class="shipment-info-value">
|
||||||
|
{{ \Carbon\Carbon::parse($shipment->shipment_date)->format('d M Y') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="shipment-info-item">
|
||||||
|
<div class="shipment-info-label">Total Orders</div>
|
||||||
|
<div class="shipment-info-value">{{ $orders->count() }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================================ -->
|
||||||
|
<!-- SHIPMENT TOTAL BLOCKS -->
|
||||||
|
<!-- ================================ -->
|
||||||
|
<h5 class="fw-bold mb-3 mt-4" style="color: #1e293b;">Shipment Summary</h5>
|
||||||
|
<div class="d-flex flex-wrap gap-3">
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL CTN</div>
|
||||||
|
<div class="total-value">{{ $shipment->total_ctn }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL QTY</div>
|
||||||
|
<div class="total-value">{{ $shipment->total_qty }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL CBM</div>
|
||||||
|
<div class="total-value">{{ $shipment->total_cbm }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL KG</div>
|
||||||
|
<div class="total-value">{{ $shipment->total_kg }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL TTL QTY</div>
|
||||||
|
<div class="total-value">{{ $shipment->total_ttl_qty }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL TTL CBM</div>
|
||||||
|
<div class="total-value">{{ $shipment->total_ttl_cbm }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL TTL KG</div>
|
||||||
|
<div class="total-value">{{ $shipment->total_ttl_kg }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="total-box">
|
||||||
|
<div class="total-title">TOTAL AMOUNT</div>
|
||||||
|
<div class="total-value text-success">
|
||||||
|
₹{{ number_format($shipment->total_amount, 2) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================================ -->
|
||||||
|
<!-- ORDERS TABLE LIST -->
|
||||||
|
<!-- ================================ -->
|
||||||
|
<h5 class="fw-bold mb-3 mt-5" style="color: #1e293b;">Orders in This Shipment</h5>
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Order ID</th>
|
||||||
|
<th>Origin</th>
|
||||||
|
<th>Destination</th>
|
||||||
|
<th>CTN</th>
|
||||||
|
<th>QTY</th>
|
||||||
|
<th>TTL/QTY</th>
|
||||||
|
<th>CBM</th>
|
||||||
|
<th>TTL CBM</th>
|
||||||
|
<th>KG</th>
|
||||||
|
<th>TTL KG</th>
|
||||||
|
<th>Amount (₹)</th>
|
||||||
|
<!-- Conditionally show Delete column header -->
|
||||||
|
@if($mode === 'edit' && $shipment->status === 'pending')
|
||||||
|
<th>Delete</th>
|
||||||
|
@endif
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@foreach($orders as $order)
|
||||||
|
<tr>
|
||||||
|
<td class="fw-bold text-primary">{{ $order->order_id }}</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>
|
||||||
|
|
||||||
|
<!-- Conditionally show Delete button -->
|
||||||
|
@if($mode === 'edit' && $shipment->status === 'pending')
|
||||||
|
<td>
|
||||||
|
<form method="POST" action="{{ route('admin.shipments.removeOrder') }}" onsubmit="return confirmDelete()">
|
||||||
|
@csrf
|
||||||
|
<input type="hidden" name="shipment_id" value="{{ $shipment->id }}">
|
||||||
|
<input type="hidden" name="order_id" value="{{ $order->id }}">
|
||||||
|
<button type="submit" class="btn btn-danger btn-sm" style="border-radius: 10px; padding: 8px 16px;">
|
||||||
|
<i class="bi bi-trash"></i> Delete
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
@endif
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Action Buttons -->
|
||||||
|
<div class="d-flex justify-content-between mt-4">
|
||||||
|
<!-- <a href="{{ route('admin.shipments') }}" class="btn btn-secondary">
|
||||||
|
<i class="bi bi-arrow-left"></i> Back to Shipments
|
||||||
|
</a>
|
||||||
|
-->
|
||||||
|
@if($mode === 'edit' && $shipment->status === 'pending')
|
||||||
|
<div>
|
||||||
|
<!-- <a href="{{ route('admin.shipments.view', ['id' => $shipment->id, 'mode' => 'edit']) }}"
|
||||||
|
class="btn btn-warning me-2">
|
||||||
|
<i class="bi bi-pencil"></i> Edit Shipment
|
||||||
|
</a> -->
|
||||||
|
|
||||||
|
<!-- <a href="{{ route('admin.shipments.view', ['id' => $shipment->id, 'mode' => 'view']) }}"
|
||||||
|
class="btn btn-info">
|
||||||
|
<i class="bi bi-eye"></i> View Mode
|
||||||
|
</a> -->
|
||||||
|
</div>
|
||||||
|
@elseif($shipment->status === 'pending')
|
||||||
|
<div>
|
||||||
|
<!-- <a href="{{ route('admin.shipments.view', ['id' => $shipment->id, 'mode' => 'edit']) }}"
|
||||||
|
class="btn btn-primary">
|
||||||
|
<i class="bi bi-pencil"></i> Edit Shipment
|
||||||
|
</a> -->
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- New Order Modal -->
|
||||||
|
<div class="modal fade" id="newOrderModal" tabindex="-1" aria-labelledby="newOrderModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="newOrderModalLabel">Add Orders to Shipment</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h6>Deleted Orders (recently removed)</h6>
|
||||||
|
<div id="deletedOrdersList" class="list-group"></div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h6>Available Orders</h6>
|
||||||
|
<div id="availableOrdersList" class="list-group"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3">
|
||||||
|
<small class="text-muted">Select orders to add back to this shipment, then click "Add Selected".</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||||
|
<button id="addSelectedOrdersBtn" type="button" class="btn btn-success">Add Selected</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function confirmDelete() {
|
||||||
|
return confirm('Are you sure you want to remove this order from the shipment?');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
const csrfToken = '{{ csrf_token() }}';
|
||||||
|
const shipmentId = {{ $shipment->id }};
|
||||||
|
let availableOrders = @json($availableOrders ?? []);
|
||||||
|
let deletedOrders = [];
|
||||||
|
|
||||||
|
function renderOrdersList(containerId, orders) {
|
||||||
|
const container = document.getElementById(containerId);
|
||||||
|
container.innerHTML = '';
|
||||||
|
if (!orders.length) {
|
||||||
|
container.innerHTML = '<div class="text-muted py-3">No orders</div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
orders.forEach(order => {
|
||||||
|
const item = document.createElement('label');
|
||||||
|
item.className = 'list-group-item d-flex justify-content-between align-items-center';
|
||||||
|
item.innerHTML = `
|
||||||
|
<div>
|
||||||
|
<input type="checkbox" class="me-2 order-checkbox" data-order='${JSON.stringify(order)}'>
|
||||||
|
<strong>${order.order_id}</strong>
|
||||||
|
<div class="small text-muted"> ${order.origin} → ${order.destination} • ${order.qty} qty • ₹${parseFloat(order.ttl_amount).toLocaleString('en-IN', {minimumFractionDigits:2})}</div>
|
||||||
|
</div>
|
||||||
|
<div class="small text-muted">ID: ${order.id}</div>
|
||||||
|
`;
|
||||||
|
container.appendChild(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderOrdersList('availableOrdersList', availableOrders);
|
||||||
|
renderOrdersList('deletedOrdersList', deletedOrders);
|
||||||
|
|
||||||
|
// Intercept remove-order forms (update selector if form action different)
|
||||||
|
document.querySelectorAll('form[action="{{ route('admin.shipments.removeOrder') }}"]').forEach(form => {
|
||||||
|
form.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!confirm('Are you sure you want to remove this order from the shipment?')) return;
|
||||||
|
|
||||||
|
const formData = new FormData(this);
|
||||||
|
|
||||||
|
fetch(this.action, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json'},
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(data => {
|
||||||
|
if (!data.success) { alert(data.message || 'Failed'); return; }
|
||||||
|
|
||||||
|
// Remove row from DOM
|
||||||
|
const row = this.closest('tr');
|
||||||
|
// Build deleted order object from row cells if present
|
||||||
|
const orderObj = {
|
||||||
|
id: formData.get('order_id'),
|
||||||
|
order_id: row ? row.querySelector('td:first-child')?.innerText.trim() : ('Order-'+formData.get('order_id')),
|
||||||
|
origin: row ? row.cells[1]?.innerText.trim() : '',
|
||||||
|
destination: row ? row.cells[2]?.innerText.trim() : '',
|
||||||
|
qty: row ? row.cells[4]?.innerText.trim() : '',
|
||||||
|
ttl_amount: row ? row.cells[10]?.innerText.replace('₹','').replace(',','').trim() : 0
|
||||||
|
};
|
||||||
|
|
||||||
|
if (row) row.remove();
|
||||||
|
|
||||||
|
deletedOrders.unshift(orderObj);
|
||||||
|
renderOrdersList('deletedOrdersList', deletedOrders);
|
||||||
|
|
||||||
|
// Optional: update totals by refetching shipment summary endpoint or reload
|
||||||
|
if (data.shipment) updateTotalsInDOM(data.shipment);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
alert('Remove failed.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Open modal from add-order button
|
||||||
|
document.querySelectorAll('.glass-btn').forEach(btn => {
|
||||||
|
btn.addEventListener('click', function(e) {
|
||||||
|
renderOrdersList('availableOrdersList', availableOrders);
|
||||||
|
renderOrdersList('deletedOrdersList', deletedOrders);
|
||||||
|
const modal = new bootstrap.Modal(document.getElementById('newOrderModal'));
|
||||||
|
modal.show();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add selected orders
|
||||||
|
document.getElementById('addSelectedOrdersBtn').addEventListener('click', function() {
|
||||||
|
const checked = Array.from(document.querySelectorAll('.order-checkbox:checked'));
|
||||||
|
if (!checked.length) { alert('Please select orders'); return; }
|
||||||
|
|
||||||
|
const orderIds = checked.map(cb => JSON.parse(cb.getAttribute('data-order')).id);
|
||||||
|
|
||||||
|
fetch(`/admin/shipments/${shipmentId}/add-orders`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json', 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json'},
|
||||||
|
body: JSON.stringify({ order_ids: orderIds })
|
||||||
|
})
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (!data.success) { alert(data.message || 'Failed'); return; }
|
||||||
|
|
||||||
|
// Update orders table — simplest approach: reload page to reflect DB
|
||||||
|
// But we can also append rows from data.orders (if provided)
|
||||||
|
location.reload();
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
alert('Add failed.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateTotalsInDOM(shipment) {
|
||||||
|
try {
|
||||||
|
if (document.getElementById('total_qty')) {
|
||||||
|
document.getElementById('total_qty').innerText = shipment.total_qty;
|
||||||
|
}
|
||||||
|
if (document.getElementById('total_amount')) {
|
||||||
|
document.getElementById('total_amount').innerText = '₹' + parseFloat(shipment.total_amount).toLocaleString('en-IN', {minimumFractionDigits:2});
|
||||||
|
}
|
||||||
|
// add other totals similarly...
|
||||||
|
} catch(e) { console.warn(e); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
document.addEventListener('hidden.bs.modal', function (event) {
|
||||||
|
document.body.classList.remove('modal-open');
|
||||||
|
let backdrop = document.querySelector('.modal-backdrop');
|
||||||
|
if (backdrop) backdrop.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
@endsection
|
||||||
@@ -131,23 +131,18 @@ Route::prefix('admin')
|
|||||||
// ---------------------------
|
// ---------------------------
|
||||||
// ORDERS (FIXED ROUTES)
|
// ORDERS (FIXED ROUTES)
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
|
|
||||||
// Add item to order
|
// Add item to order
|
||||||
Route::post('/orders/{order}/item', [AdminOrderController::class, 'addItem'])
|
Route::post('/orders/{order}/item', [AdminOrderController::class, 'addItem'])
|
||||||
->name('admin.orders.addItem');
|
->name('admin.orders.addItem');
|
||||||
|
|
||||||
// Delete item from order
|
// Delete item from order
|
||||||
Route::delete('/orders/item/{id}', [AdminOrderController::class, 'deleteItem'])
|
Route::delete('/orders/item/{id}', [AdminOrderController::class, 'deleteItem'])
|
||||||
->name('admin.orders.deleteItem');
|
->name('admin.orders.deleteItem');
|
||||||
|
|
||||||
// Restore deleted item
|
// Restore deleted item
|
||||||
Route::post('/orders/item/{id}/restore', [AdminOrderController::class, 'restoreItem'])
|
Route::post('/orders/item/{id}/restore', [AdminOrderController::class, 'restoreItem'])
|
||||||
->name('admin.orders.restoreItem');
|
->name('admin.orders.restoreItem');
|
||||||
|
|
||||||
// Update main order fields
|
// Update main order fields
|
||||||
Route::post('/orders/{id}/update', [AdminOrderController::class, 'update'])
|
Route::put('/admin/orders/item/update/{id}', [AdminOrderController::class, 'updateItem'])
|
||||||
->name('admin.orders.update');
|
->name('admin.orders.updateItem');
|
||||||
|
|
||||||
// Delete full order
|
// Delete full order
|
||||||
Route::delete('/orders/{id}/delete', [AdminOrderController::class, 'destroy'])
|
Route::delete('/orders/{id}/delete', [AdminOrderController::class, 'destroy'])
|
||||||
->name('admin.orders.destroy');
|
->name('admin.orders.destroy');
|
||||||
@@ -155,31 +150,44 @@ 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');
|
||||||
|
|
||||||
// Get shipment orders for modal (AJAX)
|
// Shipment orders (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');
|
||||||
|
|
||||||
// Get shipment details for edit (AJAX)
|
// Shipment update
|
||||||
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
|
||||||
@@ -199,19 +207,19 @@ Route::prefix('admin')
|
|||||||
Route::post('/invoices/{invoice}/installments', [AdminInvoiceController::class, 'storeInstallment'])
|
Route::post('/invoices/{invoice}/installments', [AdminInvoiceController::class, 'storeInstallment'])
|
||||||
->name('admin.invoice.installment.store');
|
->name('admin.invoice.installment.store');
|
||||||
|
|
||||||
|
Route::post('/invoices/{id}/installment', [AdminInvoiceController::class, 'storeInstallment'])
|
||||||
|
->name('admin.invoice.installment.store');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Route::delete('/installment/{id}', [AdminInvoiceController::class, 'deleteInstallment'])
|
Route::delete('/installment/{id}', [AdminInvoiceController::class, 'deleteInstallment'])
|
||||||
->name('admin.invoice.installment.delete');
|
->name('admin.invoice.installment.delete');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Add New Invoice
|
//Add New Invoice
|
||||||
Route::get('/admin/invoices/create', [InvoiceController::class, 'create'])->name('admin.invoices.create');
|
Route::get('/admin/invoices/create', [InvoiceController::class, 'create'])->name('admin.invoices.create');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
// CUSTOMERS
|
// CUSTOMERS
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
@@ -297,4 +305,3 @@ Route::prefix('admin')
|
|||||||
//Edit Button Route
|
//Edit Button Route
|
||||||
//---------------------------
|
//---------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user