diff --git a/app/Http/Controllers/Admin/AdminAccountController.php b/app/Http/Controllers/Admin/AdminAccountController.php
index d760951..8b5d98d 100644
--- a/app/Http/Controllers/Admin/AdminAccountController.php
+++ b/app/Http/Controllers/Admin/AdminAccountController.php
@@ -11,6 +11,71 @@ use Illuminate\Support\Facades\DB;
class AdminAccountController extends Controller
{
+ public function updateEntry(Request $request)
+{
+ try {
+ $data = $request->validate([
+ 'entry_no' => 'required|exists:entries,entry_no',
+ 'description' => 'required|string|max:255',
+ 'order_quantity' => 'required|numeric|min:0',
+ ]);
+
+ $entry = Entry::where('entry_no', $data['entry_no'])->first();
+
+ if (!$entry) {
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Entry not found.',
+ ], 404);
+ }
+
+ $entry->description = $data['description'];
+ $entry->order_quantity = $data['order_quantity'];
+ $entry->save();
+
+ return response()->json([
+ 'success' => true,
+ 'message' => 'Entry updated successfully.',
+ 'entry' => $entry,
+ ]);
+ } catch (\Throwable $e) {
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Server error: '.$e->getMessage(),
+ ], 500);
+ }
+}
+
+public function deleteEntry(Request $request)
+{
+ try {
+ $data = $request->validate([
+ 'entry_no' => 'required|exists:entries,entry_no',
+ ]);
+
+ $entry = Entry::where('entry_no', $data['entry_no'])->first();
+
+ if (!$entry) {
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Entry not found.',
+ ], 404);
+ }
+
+ $entry->delete();
+
+ return response()->json([
+ 'success' => true,
+ 'message' => 'Entry deleted successfully.',
+ ]);
+ } catch (\Throwable $e) {
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Server error: '.$e->getMessage(),
+ ], 500);
+ }
+}
+
/**
* 🚀 1. Get dashboard entries
*/
@@ -245,4 +310,82 @@ class AdminAccountController extends Controller
'pending' => $entry->pending_amount,
]);
}
+
+ //--------------------------
+ //add order Entry
+ //--------------------------
+ public function addOrdersToEntry(Request $request)
+{
+ $data = $request->validate([
+ 'entry_no' => 'required|exists:entries,entry_no',
+ 'order_ids' => 'required|array',
+ 'order_ids.*' => 'integer|exists:orders,id',
+ ]);
+
+ return DB::transaction(function () use ($data) {
+ $entry = Entry::where('entry_no', $data['entry_no'])->firstOrFail();
+
+ // आधीचे orders काढू नका, फक्त नवीन add करा
+ $entry->orders()->syncWithoutDetaching($data['order_ids']);
+
+ // इथे quantity auto update
+ $entry->order_quantity = $entry->orders()->count();
+ $entry->save();
+
+ $entry->load('orders');
+
+ return response()->json([
+ 'success' => true,
+ 'message' => 'Orders added successfully.',
+ 'entry' => $entry,
+ ]);
+ });
}
+
+
+
+public function getEntryOrders($entry_no)
+{
+ $entry = Entry::where('entry_no', $entry_no)
+ ->with('orders')
+ ->first();
+
+ if (!$entry) {
+ return response()->json([
+ 'success' => false,
+ 'message' => 'Entry not found.',
+ ], 404);
+ }
+
+ return response()->json([
+ 'success' => true,
+ 'orders' => $entry->orders,
+ ]);
+}
+
+public function removeOrderFromEntry(Request $request)
+{
+ $data = $request->validate([
+ 'entry_no' => 'required|exists:entries,entry_no',
+ 'order_id' => 'required|integer|exists:orders,id',
+ ]);
+
+ return DB::transaction(function () use ($data) {
+ $entry = Entry::where('entry_no', $data['entry_no'])->firstOrFail();
+
+ // order detach करा
+ $entry->orders()->detach($data['order_id']);
+
+ // इथे quantity auto update
+ $entry->order_quantity = $entry->orders()->count();
+ $entry->save();
+
+ return response()->json([
+ 'success' => true,
+ 'message' => 'Order removed successfully.',
+ 'entry' => $entry,
+ ]);
+ });
+}
+
+}
\ No newline at end of file
diff --git a/app/Http/Controllers/Admin/AdminCustomerController.php b/app/Http/Controllers/Admin/AdminCustomerController.php
index 393db9a..aab2cd1 100644
--- a/app/Http/Controllers/Admin/AdminCustomerController.php
+++ b/app/Http/Controllers/Admin/AdminCustomerController.php
@@ -9,36 +9,42 @@ use Illuminate\Support\Facades\Hash;
class AdminCustomerController extends Controller
{
+
+
// ---------------------------------------------------------
// LIST CUSTOMERS (with search + status filter)
// ---------------------------------------------------------
public function index(Request $request)
- {
- $search = $request->search;
- $status = $request->status;
+{
+ $search = $request->search;
+ $status = $request->status;
- $query = User::with(['marks', 'orders'])->orderBy('id', 'desc');
+ $query = User::with(['marks', 'orders'])->orderBy('id', 'desc');
- // SEARCH FILTER
- if (!empty($search)) {
- $query->where(function ($q) use ($search) {
- $q->where('customer_name', 'like', "%$search%")
- ->orWhere('email', 'like', "%$search%")
- ->orWhere('mobile_no', 'like', "%$search%")
- ->orWhere('customer_id', 'like', "%$search%");
- });
- }
-
- // STATUS FILTER
- if (!empty($status) && in_array($status, ['active', 'inactive'])) {
- $query->where('status', $status);
- }
-
- $customers = $query->get();
-
- return view('admin.customers', compact('customers', 'search', 'status'));
+ // SEARCH FILTER
+ if (!empty($search)) {
+ $query->where(function ($q) use ($search) {
+ $q->where('customer_name', 'like', "%$search%")
+ ->orWhere('email', 'like', "%$search%")
+ ->orWhere('mobile_no', 'like', "%$search%")
+ ->orWhere('customer_id', 'like', "%$search%");
+ });
}
+ // STATUS FILTER
+ if (!empty($status) && in_array($status, ['active', 'inactive'])) {
+ $query->where('status', $status);
+ }
+
+ // Get all customers for statistics (without pagination)
+ $allCustomers = $query->get();
+
+ // Get paginated customers for the table (10 per page)
+ $customers = $query->paginate(10);
+
+ return view('admin.customers', compact('customers', 'allCustomers', 'search', 'status'));
+}
+
// ---------------------------------------------------------
// SHOW ADD CUSTOMER FORM
// ---------------------------------------------------------
@@ -130,5 +136,6 @@ class AdminCustomerController extends Controller
return back()->with('success', 'Customer status updated.');
}
+
}
diff --git a/app/Http/Controllers/Admin/AdminOrderController.php b/app/Http/Controllers/Admin/AdminOrderController.php
index 47a1da3..ce86dfc 100644
--- a/app/Http/Controllers/Admin/AdminOrderController.php
+++ b/app/Http/Controllers/Admin/AdminOrderController.php
@@ -7,28 +7,123 @@ use Illuminate\Http\Request;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\MarkList;
+use App\Models\Invoice;
+use App\Models\InvoiceItem;
+use App\Models\User;
class AdminOrderController extends Controller
{
+ // ---------------------------
+ // LIST / DASHBOARD
+ // ---------------------------
public function index()
{
+ // raw list for admin dashboard (simple)
$orders = Order::latest()->get();
$markList = MarkList::where('status', 'active')->get();
return view('admin.dashboard', compact('orders', 'markList'));
}
- // -------------------------------------------------------------------------
- // STEP 1 : ADD TEMPORARY ITEM
- // -------------------------------------------------------------------------
+ /**
+ * Orders list (detailed)
+ */
+ // public function orderShow()
+ // {
+ // $orders = Order::with(['markList', 'shipments', 'invoice'])
+ // ->latest('id')
+ // ->get();
- public function addTempItem(Request $request)
+ // return view('admin.orders', compact('orders'));
+ // }
+
+ // ---------------------------
+ // CREATE NEW ORDER (simple DB flow)
+ // ---------------------------
+ /**
+ * Show create form (you can place create UI on separate view or dashboard)
+ */
+ public function create()
{
- // Validate item fields
- $item = $request->validate([
- 'mark_no' => 'required',
- 'origin' => 'required',
- 'destination' => 'required',
+ // return a dedicated create view - create it at resources/views/admin/orders_create.blade.php
+ // If you prefer create UI on dashboard, change this to redirect route('admin.orders.index') etc.
+ $markList = MarkList::where('status', 'active')->get();
+ return view('admin.orders_create', compact('markList'));
+ }
+
+ /**
+ * Store a new order and optionally create initial invoice
+ */
+ public function store(Request $request)
+ {
+ $data = $request->validate([
+ 'mark_no' => 'required|string',
+ 'origin' => 'nullable|string',
+ 'destination' => 'nullable|string',
+ // totals optional when creating without items
+ 'ctn' => 'nullable|numeric',
+ 'qty' => 'nullable|numeric',
+ 'ttl_qty' => 'nullable|numeric',
+ 'ttl_amount' => 'nullable|numeric',
+ 'cbm' => 'nullable|numeric',
+ 'ttl_cbm' => 'nullable|numeric',
+ 'kg' => 'nullable|numeric',
+ 'ttl_kg' => 'nullable|numeric',
+ ]);
+
+ $order = Order::create([
+ 'order_id' => $this->generateOrderId(),
+ 'mark_no' => $data['mark_no'],
+ 'origin' => $data['origin'] ?? null,
+ 'destination' => $data['destination'] ?? null,
+ 'ctn' => $data['ctn'] ?? 0,
+ 'qty' => $data['qty'] ?? 0,
+ 'ttl_qty' => $data['ttl_qty'] ?? 0,
+ 'ttl_amount' => $data['ttl_amount'] ?? 0,
+ 'cbm' => $data['cbm'] ?? 0,
+ 'ttl_cbm' => $data['ttl_cbm'] ?? 0,
+ 'kg' => $data['kg'] ?? 0,
+ 'ttl_kg' => $data['ttl_kg'] ?? 0,
+ 'status' => 'pending',
+ ]);
+
+ // If you want to auto-create an invoice at order creation, uncomment:
+ // $this->createInvoice($order);
+
+ return redirect()->route('admin.orders.show', $order->id)
+ ->with('success', 'Order created successfully.');
+ }
+
+ // ---------------------------
+ // SHOW / POPUP
+ // ---------------------------
+ public function show($id)
+ {
+ $order = Order::with('items', 'markList')->findOrFail($id);
+ $user = $this->getCustomerFromOrder($order);
+
+ return view('admin.orders_show', compact('order', 'user'));
+ }
+
+ // public function popup($id)
+ // {
+ // $order = Order::with(['items', 'markList'])->findOrFail($id);
+ // $user = $this->getCustomerFromOrder($order);
+
+ // return view('admin.popup', compact('order', 'user'));
+ // }
+
+ // ---------------------------
+ // ORDER ITEM MANAGEMENT (DB)
+ // ---------------------------
+ /**
+ * Add an item to an existing order
+ */
+ public function addItem(Request $request, $orderId)
+ {
+ $order = Order::findOrFail($orderId);
+
+ $data = $request->validate([
'description' => 'required|string',
'ctn' => 'nullable|numeric',
'qty' => 'nullable|numeric',
@@ -43,233 +138,207 @@ class AdminOrderController extends Controller
'shop_no' => 'nullable|string',
]);
- // ❌ Prevent changing mark_no once first item added
- if (session()->has('mark_no') && session('mark_no') != $request->mark_no) {
- return redirect()->to(route('admin.orders.index') . '#createOrderForm')
- ->with('error', 'You must finish or clear the current order before changing Mark No.');
- }
+ $data['order_id'] = $order->id;
- // Save mark, origin, destination ONLY ONCE
- if (!session()->has('mark_no')) {
- session([
- 'mark_no' => $request->mark_no,
- 'origin' => $request->origin,
- 'destination' => $request->destination
+ OrderItem::create($data);
+
+ // recalc totals and save to order
+ $this->recalcTotals($order);
+
+ return redirect()->back()->with('success', 'Item added and totals updated.');
+ }
+
+ /**
+ * Soft-delete an order item and recalc totals
+ */
+ public function deleteItem($id)
+ {
+ $item = OrderItem::findOrFail($id);
+ $order = $item->order;
+
+ $item->delete(); // soft delete
+
+ // recalc totals
+ $this->recalcTotals($order);
+
+ return redirect()->back()->with('success', 'Item deleted and totals updated.');
+ }
+
+ /**
+ * Restore soft-deleted item and recalc totals
+ */
+ public function restoreItem($id)
+ {
+ $item = OrderItem::withTrashed()->findOrFail($id);
+ $order = Order::findOrFail($item->order_id);
+
+ $item->restore();
+
+ // recalc totals
+ $this->recalcTotals($order);
+
+ return redirect()->back()->with('success', 'Item restored and totals updated.');
+ }
+
+ // ---------------------------
+ // ORDER CRUD: update / destroy
+ // ---------------------------
+ public function update(Request $request, $id)
+ {
+ $order = Order::findOrFail($id);
+
+ $data = $request->validate([
+ 'mark_no' => 'required|string',
+ 'origin' => 'nullable|string',
+ 'destination' => 'nullable|string',
+ ]);
+
+ $order->update([
+ 'mark_no' => $data['mark_no'],
+ 'origin' => $data['origin'] ?? null,
+ 'destination' => $data['destination'] ?? null,
+ ]);
+
+ // optionally recalc totals (not necessary unless you change item-level fields here)
+ $this->recalcTotals($order);
+
+ return redirect()->route('admin.orders.show', $order->id)
+ ->with('success', 'Order updated successfully.');
+ }
+
+ /**
+ * Soft-delete whole order and its items (soft-delete items first then order)
+ */
+ public function destroy($id)
+ {
+ $order = Order::findOrFail($id);
+
+ // soft-delete items first (so they show up in onlyTrashed for restore)
+ OrderItem::where('order_id', $order->id)->delete();
+
+ // then soft-delete order
+ $order->delete();
+
+ return redirect()->route('admin.orders.index')
+ ->with('success', 'Order deleted successfully.');
+ }
+
+ // ---------------------------
+ // HELPERS
+ // ---------------------------
+ /**
+ * Recalculate totals for the order from current (non-deleted) items
+ */
+ private function recalcTotals(Order $order)
+ {
+ // make sure we re-query live items (non-deleted)
+ $items = $order->items()->get();
+
+ $order->update([
+ 'ctn' => (int) $items->sum(fn($i) => (int) ($i->ctn ?? 0)),
+ 'qty' => (int) $items->sum(fn($i) => (int) ($i->qty ?? 0)),
+ 'ttl_qty' => (int) $items->sum(fn($i) => (int) ($i->ttl_qty ?? 0)),
+ 'ttl_amount'=> (float) $items->sum(fn($i) => (float) ($i->ttl_amount ?? 0)),
+ 'cbm' => (float) $items->sum(fn($i) => (float) ($i->cbm ?? 0)),
+ 'ttl_cbm' => (float) $items->sum(fn($i) => (float) ($i->ttl_cbm ?? 0)),
+ 'kg' => (float) $items->sum(fn($i) => (float) ($i->kg ?? 0)),
+ 'ttl_kg' => (float) $items->sum(fn($i) => (float) ($i->ttl_kg ?? 0)),
+ ]);
+ }
+
+ /**
+ * Generate order id (keeps old format)
+ */
+ private function generateOrderId()
+ {
+ $year = date('y');
+ $prefix = "KNT-$year-";
+
+ $lastOrder = Order::latest('id')->first();
+ $nextNumber = $lastOrder ? intval(substr($lastOrder->order_id, -8)) + 1 : 1;
+
+ return $prefix . str_pad($nextNumber, 8, '0', STR_PAD_LEFT);
+ }
+
+ // ---------------------------
+ // INVOICE CREATION (optional helper used by store/finish)
+ // ---------------------------
+ private function createInvoice(Order $order)
+ {
+ $invoiceNumber = $this->generateInvoiceNumber();
+ $customer = $this->getCustomerFromMarkList($order->mark_no);
+ $totalAmount = $order->ttl_amount;
+
+ $invoice = 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' => $totalAmount,
+ 'gst_percent' => 0,
+ 'gst_amount' => 0,
+ 'final_amount_with_gst' => $totalAmount,
+ '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,
+ 'pdf_path' => null,
+ ]);
+
+ // clone order items into invoice items
+ foreach ($order->items as $item) {
+ 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,
]);
}
-
- // ❌ DO NOT overwrite these values again
- // session(['mark_no' => $request->mark_no]);
- // session(['origin' => $request->origin]);
- // session(['destination' => $request->destination]);
-
- // Add new sub-item into session
- session()->push('temp_order_items', $item);
-
- return redirect()->to(route('admin.orders.index') . '#createOrderForm')
- ->with('success', 'Item added.');
}
- // -------------------------------------------------------------------------
- // STEP 2 : DELETE TEMPORARY ITEM
- // -------------------------------------------------------------------------
-
- public function deleteTempItem(Request $request)
+ private function generateInvoiceNumber()
{
- $index = $request->index;
+ $lastInvoice = Invoice::latest()->first();
+ $nextInvoice = $lastInvoice ? $lastInvoice->id + 1 : 1;
- $items = session('temp_order_items', []);
+ return 'INV-' . date('Y') . '-' . str_pad($nextInvoice, 6, '0', STR_PAD_LEFT);
+ }
- if (isset($items[$index])) {
- unset($items[$index]);
- session(['temp_order_items' => array_values($items)]);
+ private function getCustomerFromMarkList($markNo)
+ {
+ $markList = MarkList::where('mark_no', $markNo)->first();
+
+ if ($markList && $markList->customer_id) {
+ return User::where('customer_id', $markList->customer_id)->first();
}
- // If no items left → reset mark_no lock
- if (empty($items)) {
- session()->forget(['mark_no', 'origin', 'destination']);
- }
-
- return redirect()->to(route('admin.orders.index') . '#createOrderForm')
- ->with('success', 'Item removed successfully.');
+ return null;
}
- // -------------------------------------------------------------------------
- // STEP 3 : FINISH ORDER
- // -------------------------------------------------------------------------
-
- public function finishOrder(Request $request)
-{
- $request->validate([
- 'mark_no' => 'required',
- 'origin' => 'required',
- 'destination' => 'required',
- ]);
-
- $items = session('temp_order_items', []);
-
- if (empty($items)) {
- return redirect()->to(route('admin.orders.index') . '#createOrderForm')
- ->with('error', 'Add at least one item before finishing.');
- }
-
- // =======================
- // GENERATE ORDER ID
- // =======================
- $year = date('y');
- $prefix = "KNT-$year-";
-
- $lastOrder = Order::latest('id')->first();
- $nextNumber = $lastOrder ? intval(substr($lastOrder->order_id, -8)) + 1 : 1;
-
- $orderId = $prefix . str_pad($nextNumber, 8, '0', STR_PAD_LEFT);
-
- // =======================
- // TOTAL SUMS
- // =======================
- $total_ctn = array_sum(array_column($items, 'ctn'));
- $total_qty = array_sum(array_column($items, 'qty'));
- $total_ttl_qty = array_sum(array_column($items, 'ttl_qty'));
- $total_amount = array_sum(array_column($items, 'ttl_amount'));
- $total_cbm = array_sum(array_column($items, 'cbm'));
- $total_ttl_cbm = array_sum(array_column($items, 'ttl_cbm'));
- $total_kg = array_sum(array_column($items, 'kg'));
- $total_ttl_kg = array_sum(array_column($items, 'ttl_kg'));
-
- // =======================
- // CREATE ORDER
- // =======================
- $order = Order::create([
- 'order_id' => $orderId,
- 'mark_no' => $request->mark_no,
- 'origin' => $request->origin,
- 'destination' => $request->destination,
- 'ctn' => $total_ctn,
- 'qty' => $total_qty,
- 'ttl_qty' => $total_ttl_qty,
- 'ttl_amount' => $total_amount,
- 'cbm' => $total_cbm,
- 'ttl_cbm' => $total_ttl_cbm,
- 'kg' => $total_kg,
- 'ttl_kg' => $total_ttl_kg,
- 'status' => 'pending',
- ]);
-
- // SAVE ORDER ITEMS
- foreach ($items as $item) {
- OrderItem::create([
- 'order_id' => $order->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'],
- ]);
- }
-
- // =======================
- // 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
- session()->forget(['temp_order_items', 'mark_no', 'origin', 'destination']);
-
- return redirect()->route('admin.orders.index')
- ->with('success', 'Order + Invoice created successfully.');
-}
-
-
- // -------------------------------------------------------------------------
- // ORDER SHOW PAGE
- // -------------------------------------------------------------------------
-
- public function show($id)
+ private function getCustomerFromOrder($order)
{
- $order = Order::with('items', 'markList')->findOrFail($id);
-
- $user = null;
if ($order->markList && $order->markList->customer_id) {
- $user = \App\Models\User::where('customer_id', $order->markList->customer_id)->first();
+ return User::where('customer_id', $order->markList->customer_id)->first();
}
- return view('admin.orders_show', compact('order', 'user'));
+ return null;
}
public function popup($id)
@@ -309,5 +378,46 @@ class AdminOrderController extends Controller
return view('admin.orders', compact('orders'));
}
+
+public function downloadPdf(Request $request)
+{
+ $query = Order::with(['markList', 'invoice', 'shipments']);
+
+ // Apply filters
+ if ($request->has('search') && $request->search) {
+ $search = $request->search;
+ $query->where(function($q) use ($search) {
+ $q->where('order_id', 'like', "%{$search}%")
+ ->orWhereHas('markList', function($q) use ($search) {
+ $q->where('company_name', 'like', "%{$search}%");
+ })
+ ->orWhereHas('invoice', function($q) use ($search) {
+ $q->where('invoice_number', 'like', "%{$search}%");
+ });
+ });
+ }
+
+ if ($request->has('status') && $request->status) {
+ $query->whereHas('invoice', function($q) use ($request) {
+ $q->where('status', $request->status);
+ });
+ }
+
+ if ($request->has('shipment') && $request->shipment) {
+ $query->whereHas('shipments', function($q) use ($request) {
+ $q->where('status', $request->shipment);
+ });
+ }
+
+ $orders = $query->get();
+
+ $pdf = PDF::loadView('admin.orders.pdf', compact('orders'));
+ return $pdf->download('orders-report-' . date('Y-m-d') . '.pdf');
+}
+
+public function downloadExcel(Request $request)
+{
+ return Excel::download(new OrdersExport($request), 'orders-report-' . date('Y-m-d') . '.xlsx');
+}
}
diff --git a/app/Http/Controllers/Admin/ShipmentController.php b/app/Http/Controllers/Admin/ShipmentController.php
index c0883fd..d281059 100644
--- a/app/Http/Controllers/Admin/ShipmentController.php
+++ b/app/Http/Controllers/Admin/ShipmentController.php
@@ -14,7 +14,7 @@ class ShipmentController extends Controller
/**
* Show shipment page (Create Shipment + Shipment List)
*/
- public function index()
+ public function index()
{
// 1) Get all used order IDs
$usedOrderIds = ShipmentItem::pluck('order_id')->toArray();
@@ -29,8 +29,6 @@ class ShipmentController extends Controller
return view('admin.shipments', compact('availableOrders', 'shipments'));
}
-
-
/**
* Store new shipment
*/
@@ -115,8 +113,6 @@ class ShipmentController extends Controller
return redirect()->back()->with('success', "Shipment $newShipmentId created successfully!");
}
-
-
/**
* Show shipment details (for modal popup)
*/
@@ -135,8 +131,6 @@ class ShipmentController extends Controller
]);
}
-
-
/**
* Update Shipment status from action button
*/
@@ -164,5 +158,55 @@ class ShipmentController extends Controller
);
}
+ /**
+ * Update shipment details
+ */
+ public function update(Request $request, $id)
+ {
+ $shipment = Shipment::findOrFail($id);
-}
+ $data = $request->validate([
+ 'origin' => 'required|string',
+ 'destination' => 'required|string',
+ 'shipment_date' => 'required|date',
+ 'status' => 'required|string',
+ ]);
+
+ $shipment->update($data);
+
+ // If it's an AJAX request, return JSON response
+ if ($request->ajax() || $request->wantsJson()) {
+ return response()->json([
+ 'success' => true,
+ 'message' => 'Shipment updated successfully.'
+ ]);
+ }
+
+ return redirect()->back()->with('success', 'Shipment updated successfully.');
+ }
+
+ /**
+ * Delete shipment permanently
+ */
+ public function destroy($id, Request $request)
+ {
+ $shipment = Shipment::findOrFail($id);
+
+ // Delete shipment items
+ ShipmentItem::where('shipment_id', $shipment->id)->delete();
+
+ // Delete shipment itself
+ $shipment->delete();
+
+ // If it's an AJAX request, return JSON response
+ if ($request->ajax() || $request->wantsJson()) {
+ return response()->json([
+ 'success' => true,
+ 'message' => 'Shipment deleted successfully.'
+ ]);
+ }
+
+ return redirect()->route('admin.shipments')
+ ->with('success', 'Shipment deleted successfully.');
+ }
+}
\ No newline at end of file
diff --git a/app/Http/Controllers/RequestController.php b/app/Http/Controllers/RequestController.php
index 685271c..e2078c1 100644
--- a/app/Http/Controllers/RequestController.php
+++ b/app/Http/Controllers/RequestController.php
@@ -44,6 +44,8 @@ class RequestController extends Controller
'pincode' => $request->pincode,
'date' => Carbon::now()->toDateString(), // Auto current date
'status' => 'pending', // Default status
+
+
]);
// ✅ Response
diff --git a/app/Models/Order.php b/app/Models/Order.php
index d3691c8..029cf35 100644
--- a/app/Models/Order.php
+++ b/app/Models/Order.php
@@ -4,11 +4,13 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\SoftDeletes;
+
class Order extends Model
{
- use HasFactory;
-
+ use HasFactory,SoftDeletes;
+
protected $fillable = [
'order_id',
'mark_no',
diff --git a/app/Models/OrderItem.php b/app/Models/OrderItem.php
index 75cd416..6d37939 100644
--- a/app/Models/OrderItem.php
+++ b/app/Models/OrderItem.php
@@ -4,10 +4,11 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\SoftDeletes;
class OrderItem extends Model
{
- use HasFactory;
+ use HasFactory, SoftDeletes;
protected $fillable = [
'order_id',
diff --git a/database/migrations/2025_11_24_131305_create_invoice_installments_table.php b/database/migrations/2025_11_24_131305_create_invoice_installments_table.php
index f9e33cc..d1c540f 100644
--- a/database/migrations/2025_11_24_131305_create_invoice_installments_table.php
+++ b/database/migrations/2025_11_24_131305_create_invoice_installments_table.php
@@ -8,23 +8,16 @@ return new class extends Migration
{
public function up(): void
{
- Schema::create('invoice_installments', function (Blueprint $table) {
- $table->id();
-
- $table->unsignedBigInteger('invoice_id');
- $table->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
-
- $table->date('installment_date');
- $table->string('payment_method')->nullable(); // cash, bank, UPI, cheque, etc
- $table->string('reference_no')->nullable();
- $table->decimal('amount', 10, 2);
-
- $table->timestamps();
+ // Table already exists. Add updates here if needed.
+ Schema::table('invoice_installments', function (Blueprint $table) {
+ // nothing to update
});
}
public function down(): void
{
- Schema::dropIfExists('invoice_installments');
+ Schema::table('invoice_installments', function (Blueprint $table) {
+ // nothing to rollback
+ });
}
};
diff --git a/database/migrations/2025_11_28_182057_add_soft_deletes_to_orders_table.php b/database/migrations/2025_11_28_182057_add_soft_deletes_to_orders_table.php
new file mode 100644
index 0000000..4d837c8
--- /dev/null
+++ b/database/migrations/2025_11_28_182057_add_soft_deletes_to_orders_table.php
@@ -0,0 +1,22 @@
+softDeletes();
+ });
+ }
+
+ public function down(): void
+ {
+ Schema::table('order_items', function (Blueprint $table) {
+ $table->dropSoftDeletes();
+ });
+ }
+};
diff --git a/database/migrations/2025_11_29_045236_add_deleted_at_to_order_items_table.php b/database/migrations/2025_11_29_045236_add_deleted_at_to_order_items_table.php
new file mode 100644
index 0000000..660229b
--- /dev/null
+++ b/database/migrations/2025_11_29_045236_add_deleted_at_to_order_items_table.php
@@ -0,0 +1,26 @@
+softDeletes(); // adds deleted_at (nullable timestamp)
+ }
+ });
+ }
+
+ public function down(): void
+ {
+ Schema::table('order_items', function (Blueprint $table) {
+ if (Schema::hasColumn('order_items', 'deleted_at')) {
+ $table->dropSoftDeletes(); // drops deleted_at
+ }
+ });
+ }
+};
diff --git a/public/invoices/invoice-INV-2025-000026.pdf b/public/invoices/invoice-INV-2025-000026.pdf
new file mode 100644
index 0000000..619708c
Binary files /dev/null and b/public/invoices/invoice-INV-2025-000026.pdf differ
diff --git a/resources/views/admin/account.blade.php b/resources/views/admin/account.blade.php
index 454de4c..cf3d3a3 100644
--- a/resources/views/admin/account.blade.php
+++ b/resources/views/admin/account.blade.php
@@ -66,29 +66,38 @@ body {
color:#fff; border:none; padding:10px 16px; border-radius:10px; font-weight:600;
cursor:pointer; transition: transform .15s ease, box-shadow .15s;
}
-.btn.ghost { background: transparent; color:var(--primary-1); border:1px solid #dbe4f5; box-shadow:none; }
+.btn.ghost { background: transparent; color:var(--primary-1); border:1.5px solid #dbe4f5; box-shadow:none; }
.btn:hover{ transform: translateY(-3px); box-shadow: 0 8px 26px rgba(36,58,114,0.12); }
/* account panels */
.account-panels {
display:flex;
gap:22px;
- align-items:flex-start;
+ align-items:stretch;
flex-wrap:wrap;
}
+
+/* Payment block with pagination */
+.payment-block {
+ flex:1;
+ min-width:48%;
+ display: flex;
+ flex-direction: column;
+}
+
.panel-card {
background: var(--card-bg);
border-radius:12px;
box-shadow:0 8px 20px rgba(25,40,80,0.06);
- flex:1;
- min-width:48%;
padding:22px;
box-sizing:border-box;
overflow-x:auto;
transition: transform .12s, box-shadow .12s;
- min-height: 480px;
+ min-height: 520px;
display: flex;
flex-direction: column;
+ flex: 1;
+ height: 100%;
}
.panel-card:hover{ transform: translateY(-4px); box-shadow:0 12px 28px rgba(25,40,80,0.08); }
.panel-title {
@@ -139,12 +148,11 @@ tr:hover td{ background:#fbfdff; }
text-align: center;
box-shadow: 0 2px 8px rgba(33, 43, 90, 0.07);
letter-spacing: 0.1px;
- background: #6b7280; /* fallback */
+ background: #6b7280;
transition: box-shadow 0.22s, transform 0.17s, background 0.22s;
vertical-align: middle;
margin: 3px 2px;
cursor: default;
- /* subtle glass effect */
backdrop-filter: blur(2px);
width: 99px;
}
@@ -199,7 +207,7 @@ tr:hover td{ background:#fbfdff; }
-webkit-appearance:none;
width:60px;
height:24px;
- background:#f25b5b; /* RED */
+ background:#f25b5b;
border:2px solid #f25b5b;
border-radius:999px;
position:relative;
@@ -305,6 +313,7 @@ tr:hover td{ background:#fbfdff; }
margin-top: 15px;
padding: 12px 0;
border-top: 1px solid #eef3fb;
+ margin-right:550px;
}
.pagination-info {
@@ -317,6 +326,8 @@ tr:hover td{ background:#fbfdff; }
display: flex;
align-items: center;
gap: 8px;
+ margin-right:-1050px;
+
}
.pagination-btn {
@@ -505,6 +516,190 @@ tr:hover td{ background:#fbfdff; }
margin-top:16px;
}
+/* Filter section styles - FOR BOTH TABLES */
+.payment-filters, .order-filters {
+ display: flex;
+ gap: 12px;
+ align-items: center;
+ margin-bottom: 16px;
+ flex-wrap: wrap;
+ padding: 14px 16px;
+ background: linear-gradient(90deg, #f8fbff, #f5f9ff);
+ border-radius: 10px;
+ border: 1px solid #eef3fb;
+ width: 480px;
+ max-width: 480px;
+}
+
+.filter-group {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+}
+
+.filter-label {
+ font-size: 13px;
+ font-weight: 600;
+ color: var(--primary-1);
+}
+
+.filter-control {
+ padding: 8px 12px;
+ border-radius: 8px;
+ border: 1px solid #e3eaf6;
+ background: #fff;
+ font-size: 14px;
+ min-width: 140px;
+}
+
+.filter-control:focus {
+ outline: none;
+ border-color: var(--primary-1);
+ box-shadow: 0 0 0 2px rgba(26, 41, 81, 0.1);
+}
+
+.filter-actions {
+ display: flex;
+ gap: 8px;
+ align-items: flex-end;
+}
+
+/* Action buttons in table */
+.action-btn {
+ background: transparent;
+ border: none;
+ cursor: pointer;
+ padding: 6px 8px;
+ border-radius: 6px;
+ transition: all 0.2s ease;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.edit-btn {
+ color: var(--primary-1);
+}
+
+.edit-btn:hover {
+ background: rgba(26, 41, 81, 0.08);
+}
+
+.delete-btn {
+ color: var(--danger);
+}
+
+.delete-btn:hover {
+ background: rgba(239, 79, 79, 0.08);
+}
+
+.action-btns {
+ display: flex;
+ gap: 4px;
+ justify-content: center;
+}
+
+/* Edit modal styles */
+.edit-modal .modal-box1 {
+ max-width: 800px;
+}
+
+.edit-form-grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 16px;
+ margin-bottom: 16px;
+}
+
+.edit-form-actions {
+ display: flex;
+ gap: 12px;
+ justify-content: flex-end;
+ margin-top: 20px;
+}
+
+/* Order management in edit modal */
+.order-management-section {
+ margin-top: 20px;
+ border-top: 1px solid #eef3fb;
+ padding-top: 16px;
+}
+
+.order-management-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 12px;
+}
+
+.order-management-title {
+ font-weight: 700;
+ color: var(--primary-1);
+ font-size: 16px;
+}
+
+.orders-table-container {
+ max-height: 300px;
+ overflow-y: auto;
+ border: 1px solid #eef3fb;
+ border-radius: 8px;
+ margin-bottom: 12px;
+}
+
+.orders-table {
+ width: 100%;
+ border-collapse: collapse;
+ font-size: 13px;
+}
+
+.orders-table th {
+ background: #f8fbff;
+ padding: 10px 12px;
+ text-align: left;
+ font-weight: 600;
+ color: var(--primary-1);
+ border-bottom: 1px solid #eef3fb;
+ position: sticky;
+ top: 0;
+}
+
+.orders-table td {
+ padding: 10px 12px;
+ border-bottom: 1px solid #f1f6ff;
+}
+
+.order-actions {
+ display: flex;
+ gap: 6px;
+}
+
+.remove-order-btn {
+ background: var(--danger);
+ color: white;
+ border: none;
+ border-radius: 4px;
+ padding: 4px 8px;
+ font-size: 12px;
+ cursor: pointer;
+ transition: background 0.2s;
+}
+
+.remove-order-btn:hover {
+ background: #d42c3f;
+}
+
+/* Add Order Modal */
+.add-order-modal .modal-box1 {
+ max-width: 1000px;
+}
+
+.add-order-actions {
+ display: flex;
+ justify-content: flex-end;
+ gap: 12px;
+ margin-top: 16px;
+}
+
/* responsive */
@media (max-width:980px){
.create-grid { grid-template-columns: 1fr; }
@@ -514,6 +709,10 @@ tr:hover td{ background:#fbfdff; }
.pagination-controls { justify-content: center; }
.account-container { padding: 20px; }
.panel-card { padding: 18px; }
+ .payment-filters, .order-filters { flex-direction: column; align-items: stretch; }
+ .filter-group { width: 100%; }
+ .filter-control { min-width: auto; }
+ .edit-form-grid { grid-template-columns: 1fr; }
}
@media (max-width:768px){
@@ -522,6 +721,27 @@ tr:hover td{ background:#fbfdff; }
.top-actions .left { justify-content: center; }
.entry-summary-cards { gap: 12px; }
.entry-summary-card { min-width: 140px; }
+ .edit-form-grid { grid-template-columns: 1fr; }
+ .order-management-header { flex-direction: column; align-items: flex-start; gap: 10px; }
+}
+
+/* Table pagination wrapper */
+.table-pagination-wrapper {
+ margin-top: 20px;
+ border-top: 1px solid #eef3fb;
+ padding-top: 15px;
+}
+
+/* Modal pagination wrapper */
+.modal-pagination-wrapper {
+ margin-top: 15px;
+ border-top: 1px solid #eef3fb;
+ padding-top: 12px;
+}
+
+/* Right-aligned pagination */
+.pagination-right {
+ justify-content: flex-end;
}
@@ -540,7 +760,7 @@ tr:hover td{ background:#fbfdff; }
Search
- + Create New Order
+ + Create New Installment
@@ -551,29 +771,104 @@ tr:hover td{ background:#fbfdff; }
-
-
-
Payment Sent to China
-
Total entries: 0
+
+
+
+
+ Payment Sent to China
+ Total entries: 0
+
+
+
+
+
+ Date Filter
+
+
+
+
+ Status Filter
+
+ All Statuses
+ Paid
+ Unpaid
+ Pending
+
+
+
+
+ Clear Filters
+
+
+
+
+
+
+ Entry No Date Description
+ Order Quantity Region Payment Amount Status
+ Actions
+
+
+
+
+
+
+
+ nt
+
+
-
-
-
- Entry No Date Description
- Order Quantity Region Payment Amount Status
-
-
-
- Loading entries...
-
-
+
Order Dispatch Status
Actions: + Add Installment
+
+
+
+
+ Date Filter
+
+
+
+
+ Status Filter
+
+ All Statuses
+ Pending
+ Loading
+ Packed
+ Dispatched
+ Delivered
+
+
+
+
+ Clear Filters
+
+
+
@@ -583,9 +878,10 @@ tr:hover td{ background:#fbfdff; }
- Loading entries...
+
+
@@ -594,7 +890,7 @@ tr:hover td{ background:#fbfdff; }
-
Create New Order
+
Create New Installment
✕
@@ -649,29 +945,29 @@ tr:hover td{ background:#fbfdff; }
- Loading available orders...
+
-
-
@@ -779,26 +1073,190 @@ tr:hover td{ background:#fbfdff; }
+
+
+
+
+
+
Update the description and order quantity for this entry
+
+
+
+
+
+
+
+
+
+
Add Orders to Entry
+
✕
+
+
+
Select orders to associate with this entry
+
+
+
+
+
+
+ Order ID
+ Mark No
+ Origin
+ Destination
+ CTN
+ QTY
+ Amount (₹)
+
+
+
+
+
+
+
+
+
+
+
+
+ Cancel
+ Add Selected Orders
+
+
+
+
@endsection
\ No newline at end of file
diff --git a/resources/views/admin/customers.blade.php b/resources/views/admin/customers.blade.php
index dd20aef..3321dc2 100644
--- a/resources/views/admin/customers.blade.php
+++ b/resources/views/admin/customers.blade.php
@@ -5,6 +5,14 @@
@section('content')
-
+
-
Customer List
+ Customer List
-
-
-
-
{{ $customers->count() }}
-
Total Customers
-
+
+
+
+
+
+
+
+
+
{{ $allCustomers->count() }}
+
Total Customers
+
-
-
- @php
- $newThisMonth = $customers->filter(function($customer) {
- return $customer->created_at->format('Y-m') === now()->format('Y-m');
- })->count();
- @endphp
- {{ $newThisMonth }}
+
+
+
+
+
+
+
+ @php
+ $newThisMonth = $allCustomers->filter(function($customer) {
+ return $customer->created_at->format('Y-m') === now()->format('Y-m');
+ })->count();
+ @endphp
+ {{ $newThisMonth }}
+
+
New This Month
-
New This Month
-
-
-
- @php
- $activeCustomers = $customers->where('status', 'active')->count();
- @endphp
- {{ $activeCustomers }}
+
+
+
+
+
+
+
+ @php
+ $activeCustomers = $allCustomers->where('status', 'active')->count();
+ @endphp
+ {{ $activeCustomers }}
+
+
Active Customers
-
Active Customers
-
-
-
- @php
- $premiumCount = $customers->where('customer_type', 'premium')->count();
- @endphp
- {{ $premiumCount }}
+
+
+
+
+
+
+
+ @php
+ $premiumCount = $allCustomers->where('customer_type', 'premium')->count();
+ @endphp
+ {{ $premiumCount }}
+
+
Premium Customers
-
Premium Customers
-
-
+
@@ -1167,6 +1446,14 @@ document.addEventListener('DOMContentLoaded', function() {
const closeBtn = document.getElementById('closeCreateOrderModal');
const clearFormBtn = document.getElementById('clearForm');
+ // Pagination state
+ let currentPage = 1;
+ const ordersPerPage = 10;
+ let allOrders = @json($orders->values());
+
+ // Initialize pagination
+ initializePagination();
+
// Reset temp data function
const resetTempData = () => {
fetch('{{ route("admin.orders.temp.reset") }}', {
@@ -1265,6 +1552,174 @@ document.addEventListener('DOMContentLoaded', function() {
});
});
});
+
+ /* ---------- Pagination Functions ---------- */
+ function initializePagination() {
+ renderOrdersTable(allOrders);
+ updatePaginationControls();
+
+ // Bind pagination buttons
+ document.getElementById('prevPageBtn').addEventListener('click', goToPreviousPage);
+ document.getElementById('nextPageBtn').addEventListener('click', goToNextPage);
+ }
+
+ function goToPreviousPage() {
+ if (currentPage > 1) {
+ currentPage--;
+ renderOrdersTable(allOrders);
+ updatePaginationControls();
+ }
+ }
+
+ function goToNextPage() {
+ const totalPages = Math.ceil(allOrders.length / ordersPerPage);
+ if (currentPage < totalPages) {
+ currentPage++;
+ renderOrdersTable(allOrders);
+ updatePaginationControls();
+ }
+ }
+
+ function updatePaginationControls() {
+ const totalPages = Math.ceil(allOrders.length / ordersPerPage);
+ const prevBtn = document.getElementById('prevPageBtn');
+ const nextBtn = document.getElementById('nextPageBtn');
+ const pageInfo = document.getElementById('pageInfo');
+ const paginationPages = document.getElementById('paginationPages');
+
+ prevBtn.disabled = currentPage === 1;
+ nextBtn.disabled = currentPage === totalPages || totalPages === 0;
+
+ // Update page info text
+ const startIndex = (currentPage - 1) * ordersPerPage + 1;
+ const endIndex = Math.min(currentPage * ordersPerPage, allOrders.length);
+ pageInfo.textContent = `Showing ${startIndex} to ${endIndex} of ${allOrders.length} entries`;
+
+ // Generate page numbers
+ paginationPages.innerHTML = '';
+
+ if (totalPages <= 7) {
+ // Show all pages
+ for (let i = 1; i <= totalPages; i++) {
+ addPageButton(i, paginationPages);
+ }
+ } else {
+ // Show first page, current page range, and last page
+ addPageButton(1, paginationPages);
+
+ if (currentPage > 3) {
+ paginationPages.innerHTML += '';
+ }
+
+ const start = Math.max(2, currentPage - 1);
+ const end = Math.min(totalPages - 1, currentPage + 1);
+
+ for (let i = start; i <= end; i++) {
+ addPageButton(i, paginationPages);
+ }
+
+ if (currentPage < totalPages - 2) {
+ paginationPages.innerHTML += '';
+ }
+
+ addPageButton(totalPages, paginationPages);
+ }
+ }
+
+ function addPageButton(pageNumber, container) {
+ const button = document.createElement('button');
+ button.className = 'pagination-page-btn';
+ if (pageNumber === currentPage) {
+ button.classList.add('active');
+ }
+ button.textContent = pageNumber;
+ button.addEventListener('click', () => {
+ currentPage = pageNumber;
+ renderOrdersTable(allOrders);
+ updatePaginationControls();
+ });
+ container.appendChild(button);
+ }
+
+ function renderOrdersTable(orders) {
+ const tbody = document.getElementById('ordersTableBody');
+ tbody.innerHTML = '';
+
+ if (!orders || orders.length === 0) {
+ tbody.innerHTML = '
No orders found ';
+ return;
+ }
+
+ // Calculate pagination
+ const startIndex = (currentPage - 1) * ordersPerPage;
+ const endIndex = startIndex + ordersPerPage;
+ const paginatedOrders = orders.slice(startIndex, endIndex);
+
+ paginatedOrders.forEach(order => {
+ const tr = document.createElement('tr');
+ tr.innerHTML = `
+
${order.id}
+
+
+ ${order.order_id}
+
+
+
${order.mark_no || ''}
+
${order.origin || ''}
+
${order.destination || ''}
+
${order.ctn || ''}
+
${order.qty || ''}
+
${order.ttl_qty || ''}
+
₹${order.ttl_amount ? Number(order.ttl_amount).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) : '0.00'}
+
${order.cbm || ''}
+
${order.ttl_cbm || ''}
+
${order.kg || ''}
+
${order.ttl_kg || ''}
+
+
+ ${order.status === 'pending' ? ' ' : ''}
+ ${order.status === 'in_transit' ? ' ' : ''}
+ ${order.status === 'dispatched' ? ' ' : ''}
+ ${order.status === 'delivered' ? ' ' : ''}
+ ${order.status ? order.status.charAt(0).toUpperCase() + order.status.slice(1).replace('_', ' ') : ''}
+
+
+
${new Date(order.created_at).toLocaleDateString('en-GB')}
+
+
+ View
+
+
+ `;
+ tbody.appendChild(tr);
+
+ // Re-bind order details modal for newly rendered rows
+ const orderLink = tr.querySelector('.open-order-modal');
+ if (orderLink) {
+ orderLink.addEventListener('click', function() {
+ let id = this.dataset.id;
+ let modal = new bootstrap.Modal(document.getElementById('orderDetailsModal'));
+
+ document.getElementById('orderDetailsBody').innerHTML =
+ "
Loading...
";
+
+ modal.show();
+
+ fetch(`/admin/orders/view/${id}`)
+ .then(response => response.text())
+ .then(html => {
+ document.getElementById('orderDetailsBody').innerHTML = html;
+ })
+ .catch(() => {
+ document.getElementById('orderDetailsBody').innerHTML =
+ "
Failed to load order details.
";
+ });
+ });
+ }
+ });
+ }
});
diff --git a/resources/views/admin/invoice.blade.php b/resources/views/admin/invoice.blade.php
index 2c4e0b4..84aa37a 100644
--- a/resources/views/admin/invoice.blade.php
+++ b/resources/views/admin/invoice.blade.php
@@ -4,1210 +4,1659 @@
@section('content')
-
-
-
-
- Invoice Management
-
-
-
-
-
diff --git a/resources/views/admin/orders.blade.php b/resources/views/admin/orders.blade.php
index 9d421ba..865844d 100644
--- a/resources/views/admin/orders.blade.php
+++ b/resources/views/admin/orders.blade.php
@@ -5,250 +5,1090 @@
@section('content')
-{{-- Make sure you include Font Awesome CDN in your main layout file, e.g., in :
-
---}}
-
-
-
Orders List
+
+ Orders Management
+
+
+
+
+
+
{{ $orders->count() }}
+
Total Orders
+
+
{{ $orders->where('invoice.status', 'paid')->count() }}
+
Paid Invoices
+
+
+
{{ $orders->where('invoice.status', 'pending')->count() }}
+
Pending Invoices
+
+
+
{{ $orders->where('invoice.status', 'overdue')->count() }}
+
Overdue Invoices
+
+
- @if(isset($orders) && $orders->count() > 0)
-
-
-
-
- Order ID
- Shipment ID
- Customer ID
- Company
- Origin
- Destination
- Order Date
- Invoice No
- Invoice Date
- Amount
- Amount + GST
- Invoice Status
- Shipment Status
- Action
-
-
+
+
+ count() == 0 ? 'disabled' : '' }}>
+
+ Download PDF
+
+ count() == 0 ? 'disabled' : '' }}>
+
+ Download Excel
+
+
-
- @foreach($orders as $order)
+
+
+
+
+
+
+
+ All Status
+ Paid
+ Pending
+ Overdue
+
+
+ All Shipments
+ Pending
+ In Transit
+ Dispatched
+ Delivered
+
+
- @php
- $mark = $order->markList ?? null;
- $invoice = $order->invoice ?? null;
- $shipment = $order->shipments->first() ?? null;
- $invoiceStatus = strtolower($invoice->status ?? '');
- $shipmentStatus = strtolower(str_replace('_', ' ', $shipment->status ?? ''));
- @endphp
+ @if(isset($orders) && $orders->count() > 0)
+
+
+
+
+ Order ID
+ Shipment ID
+ Customer ID
+ Company
+ Origin
+ Destination
+ Order Date
+ Invoice No
+ Invoice Date
+ Amount
+ Amount + GST
+ Invoice Status
+ Shipment Status
+ Action
+
+
-
- {{ $order->order_id ?? '-' }}
- {{ $shipment->shipment_id ?? '-' }}
- {{ $mark->customer_id ?? '-' }}
- {{ $mark->company_name ?? '-' }}
- {{ $mark->origin ?? $order->origin ?? '-' }}
- {{ $mark->destination ?? $order->destination ?? '-' }}
- {{ $order->created_at ? $order->created_at->format('d-m-Y') : '-' }}
+
+ @foreach($orders as $order)
+ @php
+ $mark = $order->markList ?? null;
+ $invoice = $order->invoice ?? null;
+ $shipment = $order->shipments->first() ?? null;
+ $invoiceStatus = strtolower($invoice->status ?? '');
+ $shipmentStatus = strtolower(str_replace('_', ' ', $shipment->status ?? ''));
+ @endphp
- {{ $invoice->invoice_number ?? '-' }}
+
+ {{ $order->order_id ?? '-' }}
+ {{ $shipment->shipment_id ?? '-' }}
+ {{ $mark->customer_id ?? '-' }}
+ {{ $mark->company_name ?? '-' }}
+ {{ $mark->origin ?? $order->origin ?? '-' }}
+ {{ $mark->destination ?? $order->destination ?? '-' }}
+ {{ $order->created_at ? $order->created_at->format('d-m-Y') : '-' }}
-
- {{ $invoice?->invoice_date ? date('d-m-Y', strtotime($invoice->invoice_date)) : '-' }}
-
+ {{ $invoice->invoice_number ?? '-' }}
-
- {{ $invoice?->final_amount ? '₹'.number_format($invoice->final_amount, 2) : '-' }}
-
+
+ {{ $invoice?->invoice_date ? date('d-m-Y', strtotime($invoice->invoice_date)) : '-' }}
+
-
- {{ $invoice?->final_amount_with_gst ? '₹'.number_format($invoice->final_amount_with_gst, 2) : '-' }}
-
+
+ {{ $invoice?->final_amount ? '₹'.number_format($invoice->final_amount, 2) : '-' }}
+
-
- @if($invoice?->status)
-
- {{ ucfirst($invoice->status) }}
-
- @else
- Pending
- @endif
-
+
+ {{ $invoice?->final_amount_with_gst ? '₹'.number_format($invoice->final_amount_with_gst, 2) : '-' }}
+
-
- @if($shipment?->status)
-
- {{ ucfirst($shipmentStatus) }}
-
- @else
- -
- @endif
-
+
+ @if($invoice?->status)
+
+ {{ ucfirst($invoice->status) }}
+
+ @else
+ Pending
+ @endif
+
-
-
-
-
-
-
+
+ @if($shipment?->status)
+
+ {{ ucfirst($shipmentStatus) }}
+
+ @else
+ Pending
+ @endif
+
- @endforeach
-
-
-
{{-- End table-wrapper --}}
- @else
-
- No orders found.
-
- @endif
+
+
+
+
+
+
+ @endforeach
+
+
+
{{-- End table-wrapper --}}
+
+
+
+ @else
+
+
+
No orders found
+
There are currently no orders in the system.
+
+ @endif
+
+
@endsection
\ No newline at end of file
diff --git a/resources/views/admin/orders_show.blade.php b/resources/views/admin/orders_show.blade.php
index e9c1d8e..2810649 100644
--- a/resources/views/admin/orders_show.blade.php
+++ b/resources/views/admin/orders_show.blade.php
@@ -5,28 +5,96 @@
@section('content')
- {{-- Header --}}
+ {{-- HEADER --}}
+
+ {{-- TOP BAR --}}
-
Order Details
+ Order Details
Detailed view of this shipment order
+ {{-- ACTION BUTTONS --}}
+
+
+ {{-- ADD ITEM --}}
+
+ Add New Item
+
+
+ {{-- EDIT ORDER --}}
+ @if($order->status === 'pending')
+
+ Edit Order
+
+ @else
+ Edit Order
+ @endif
+
+ {{-- DELETE ORDER --}}
+ @if($order->status === 'pending')
+
+ @endif
+
+
+
- {{-- Customer Info --}}
+ {{-- EDIT ORDER FORM --}}
+
+
+ {{-- CUSTOMER INFO --}}
-
{{ strtoupper(substr($user->customer_name ?? 'U', 0, 1)) }}
+
{{ $user->customer_name ?? 'Unknown Customer' }}
{{ $user->company_name ?? 'N/A' }}
@@ -34,13 +102,14 @@
{{ $user->mobile_no ?? '' }}
+
{{ $user->address ?? '' }}
{{ $user->pincode ?? '' }}
- {{-- Order Summary --}}
+ {{-- ORDER SUMMARY --}}
- {{-- Origin - Destination --}}
+ {{-- ORIGIN / DESTINATION --}}
Origin
@@ -77,7 +146,7 @@
- {{-- Order Items Table --}}
+ {{-- ITEMS TABLE --}}
@@ -88,15 +157,17 @@
QTY
TTL/QTY
Unit
- Price (₹)
- TTL Amount (₹)
+ Price
+ Total Amount
CBM
TTL CBM
KG
TTL KG
Shop No
+ Actions
+
@foreach($order->items as $index => $item)
@@ -113,38 +184,531 @@
{{ $item->kg }}
{{ $item->ttl_kg }}
{{ $item->shop_no }}
+
+
+
+
@endforeach
- {{-- Totals --}}
+ {{-- TOTALS --}}
{{ $order->ctn }}
- Total CTN
+ Total CTN
{{ $order->qty }}
- Total QTY
+ Total QTY
{{ $order->ttl_kg }}
- Total TTL KG
+ Total KG
₹{{ number_format($order->ttl_amount, 2) }}
- Total Amount
+ Total Amount
-
-@endsection
+{{-- ADD ITEM MODAL --}}
+
+
+{{-- AUTO-FILL SCRIPT --}}
+
+
+
+
+@endsection
\ No newline at end of file
diff --git a/resources/views/admin/pdf/order_pdf.blade.php b/resources/views/admin/pdf/order_pdf.blade.php
new file mode 100644
index 0000000..906dea3
--- /dev/null
+++ b/resources/views/admin/pdf/order_pdf.blade.php
@@ -0,0 +1,43 @@
+
+
+
+
+
Orders Report
+
+
+
+
Orders Report
+
+
+
+ Order ID
+ Company
+ Invoice No
+ Invoice Status
+ Shipment Status
+
+
+
+ @foreach($orders as $order)
+ @php
+ $mark = $order->markList ?? null;
+ $invoice = $order->invoice ?? null;
+ $shipment = $order->shipments->first() ?? null;
+ @endphp
+
+ {{ $order->order_id ?? '-' }}
+ {{ $mark->company_name ?? '-' }}
+ {{ $invoice->invoice_number ?? '-' }}
+ {{ $invoice->status ?? '-' }}
+ {{ $shipment->status ?? '-' }}
+
+ @endforeach
+
+
+
+
diff --git a/resources/views/admin/reports.blade.php b/resources/views/admin/reports.blade.php
index 8049351..d0d088a 100644
--- a/resources/views/admin/reports.blade.php
+++ b/resources/views/admin/reports.blade.php
@@ -6,20 +6,28 @@
-
+
-
User Requests
-
-
- {{ $requests->where('status', 'pending')->count() }} Pending
-
-
- {{ $requests->where('status', 'approved')->count() }} Approved
-
-
- {{ $requests->where('status', 'rejected')->count() }} Rejected
-
-
+
User Requests (Total: {{ $total }})
+
+
diff --git a/resources/views/admin/shipments.blade.php b/resources/views/admin/shipments.blade.php
index 81b7d96..4092ae7 100644
--- a/resources/views/admin/shipments.blade.php
+++ b/resources/views/admin/shipments.blade.php
@@ -7,15 +7,18 @@
/*Remove horizontal scroll bar*/
html, body {
overflow-x: hidden !important;
+ font-family: 'Inter', sans-serif;
}
.table thead th,
.table tbody td {
white-space: nowrap !important;
- padding: 8px 4px !important;
+ padding: 14px 8px !important;
+ font-size: 14px;
+ font-family: 'Inter', sans-serif;
}
- .table th:nth-child(10), /* if Date is column 10 */
+ .table th:nth-child(10),
.table td:nth-child(10) {
max-width: 110px !important;
width: 110px !important;
@@ -25,6 +28,7 @@
.table {
table-layout: fixed !important;
+ font-family: 'Inter', sans-serif;
}
@@ -32,6 +36,7 @@
min-width: unset !important;
width: 100% !important;
table-layout: auto !important;
+ font-family: 'Inter', sans-serif;
}
.table thead th,
@@ -42,6 +47,8 @@
.shipment-details-table td {
white-space: normal !important;
word-break: break-word;
+ font-family: 'Inter', sans-serif;
+ font-size: 14px;
}
.table-responsive, .modal .table-responsive {
@@ -63,62 +70,125 @@
--hover-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
+ /* Search Bar Styles */
.search-shipment-bar {
display: flex;
align-items: center;
gap: 15px;
padding: 20px;
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ background: white;
border-radius: 16px;
box-shadow: var(--card-shadow);
flex-wrap: wrap;
margin-bottom: 30px;
- color: white;
+ color: #333;
position: relative;
overflow: hidden;
+ font-family: 'Inter', sans-serif;
+ border: 1px solid #e2e8f0;
}
- .search-shipment-bar::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: rgba(255,255,255,0.1);
- z-index: 0;
- }
-
- .search-shipment-bar > * {
- position: relative;
- z-index: 1;
- }
-
- .search-shipment-bar input,
- .search-shipment-bar select {
- padding: 12px 16px;
- border: 1px solid rgba(255,255,255,0.2);
- border-radius: 10px;
+ .search-input-container {
+ display: flex;
flex: 1;
- min-width: 150px;
- background: rgba(255,255,255,0.9);
- font-weight: 500;
+ min-width: 300px;
+ background: white;
+ border-radius: 10px;
+ overflow: hidden;
+ border: 1px solid #d1d5db;
transition: all 0.3s ease;
}
- .search-shipment-bar input:focus,
+ .search-input-container:focus-within {
+ border-color: #4361ee;
+ 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;
+ }
+
+ .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 select {
+ padding: 20px 16px;
+ border: 1px solid #d1d5db;
+ border-radius: 10px;
+ min-width: 150px;
+ background: white;
+ font-weight: 500;
+ transition: all 0.3s ease;
+ font-family: 'Inter', sans-serif;
+ font-size: 14px;
+ color: #333;
+ }
+
.search-shipment-bar select:focus {
background: white;
- box-shadow: 0 0 0 3px rgba(255,255,255,0.3);
+ box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.1);
outline: none;
+ border-color: #4361ee;
}
.btn-add-shipment {
- background: rgba(255,255,255,0.2);
- backdrop-filter: blur(10px);
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
- border: 1px solid rgba(255,255,255,0.3);
- padding: 12px 24px;
+ border: none;
+ padding: 17px 24px;
border-radius: 10px;
cursor: pointer;
display: flex;
@@ -127,17 +197,13 @@
transition: all 0.3s ease;
white-space: nowrap;
font-weight: 600;
+ font-family: 'Inter', sans-serif;
+ font-size: 14px;
}
.btn-add-shipment:hover {
- background: rgba(255,255,255,0.3);
transform: translateY(-2px);
- box-shadow: 0 10px 20px rgba(0,0,0,0.1);
- }
-
- .search-icon {
- font-size: 20px;
- filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1));
+ box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
}
.truck-icon {
@@ -149,7 +215,7 @@
flex-direction: column;
align-items: stretch;
}
- .search-shipment-bar input,
+ .search-input-container,
.search-shipment-bar select {
width: 100%;
}
@@ -162,6 +228,7 @@
box-shadow: var(--card-shadow);
transition: all 0.3s ease;
overflow: hidden;
+ font-family: 'Inter', sans-serif;
}
.card:hover {
@@ -175,6 +242,7 @@
border: none;
padding: 20px 25px;
border-radius: 16px 16px 0 0 !important;
+ font-family: 'Inter', sans-serif;
}
.card-header h5 {
@@ -183,6 +251,8 @@
display: flex;
align-items: center;
gap: 10px;
+ font-family: 'Inter', sans-serif;
+ font-size: 18px;
}
/* Table Styles */
@@ -198,6 +268,7 @@
width: 100%;
min-width: 1200px;
padding: 0;
+ font-family: 'Inter', sans-serif;
}
.table thead th {
@@ -211,6 +282,8 @@
border-bottom: 2px solid var(--border);
position: relative;
white-space: nowrap;
+ font-family: 'Inter', sans-serif;
+ font-size: 14px;
}
.table thead th:first-child {
@@ -239,13 +312,15 @@
border-bottom: 1px solid var(--border);
font-weight: 500;
white-space: nowrap;
+ font-family: 'Inter', sans-serif;
+ font-size: 14px;
}
.table tbody tr:last-child td {
border-bottom: none;
}
- /* UPDATED: Status Badge Styles - ALL SAME SIZE */
+ /* Status Badge Styles */
.badge {
padding: 7px 17px !important;
border-radius: 20px !important;
@@ -254,63 +329,51 @@
border: 2px solid transparent !important;
min-width: 40px !important;
text-align: center !important;
- display: inline-block !important;
+ display: inline-flex !important;
+ align-items: center;
+ justify-content: center;
line-height: 1.2 !important;
+ font-family: 'Inter', sans-serif;
+ gap: 6px;
+ width: 110px;
}
- /* Pending Status - SAME SIZE */
+ /* Status icons */
+ .status-icon {
+ font-size: 13px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ /* Pending Status */
.badge-pending {
background: linear-gradient(135deg, #fef3c7, #fde68a) !important;
color: #d97706 !important;
border-color: #f59e0b !important;
- width: 110px;
}
- /* In Transit Status - SAME SIZE */
+ /* In Transit Status */
.badge-in_transit {
background: linear-gradient(135deg, #dbeafe, #93c5fd) !important;
color: #1e40af !important;
border-color: #3b82f6 !important;
- width: 110px;
}
- /* Dispatched Status - SAME SIZE */
+ /* Dispatched Status */
.badge-dispatched {
background: linear-gradient(135deg, #e9d5ff, #c4b5fd) !important;
color: #6b21a8 !important;
border-color: #8b5cf6 !important;
- width: 110px;
}
- /* Delivered Status - SAME SIZE */
+ /* Delivered Status */
.badge-delivered {
background: linear-gradient(135deg, #d1fae5, #a7f3d0) !important;
color: #065f46 !important;
border-color: #10b981 !important;
- width: 110px;
}
- /* Default badge styles - SAME SIZE */
- .badge.bg-info {
- background: linear-gradient(135deg, #4cc9f0, #4361ee) !important;
- color: white !important;
- }
-
- .badge.bg-success {
- background: linear-gradient(135deg, #4ade80, #22c55e) !important;
- color: white !important;
- }
-
- .badge.bg-warning {
- background: linear-gradient(135deg, #fbbf24, #f59e0b) !important;
- color: white !important;
- }
-
- .badge.bg-danger {
- background: linear-gradient(135deg, #f87171, #ef4444) !important;
- color: white !important;
- }
-
/* Light badges for quantity, kg, cbm */
.badge.bg-light {
background: #f8f9fa !important;
@@ -318,9 +381,12 @@
border: 1px solid #dee2e6 !important;
min-width: 80px !important;
padding: 6px 12px !important;
+ font-family: 'Inter', sans-serif;
+ font-size: 13px;
+ width: auto;
}
- /* NEW: Action Button Styles */
+ /* Action Button Styles */
.action-container {
position: relative;
display: inline-block;
@@ -339,6 +405,7 @@
justify-content: center;
width: 36px;
height: 36px;
+ font-family: 'Inter', sans-serif;
}
.btn-edit-status:hover {
@@ -362,6 +429,7 @@
margin-top: -50px;
border: 1px solid var(--border);
z-index: 1050;
+ font-family: 'Inter', sans-serif;
}
.status-dropdown.show {
@@ -382,6 +450,7 @@
gap: 8px;
background: transparent;
width: 100%;
+ font-family: 'Inter', sans-serif;
}
.status-option:hover {
@@ -447,12 +516,73 @@
background: #10b981;
}
+ /* View Button Styles */
+ .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-content {
border-radius: 20px;
border: none;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
overflow: hidden;
+ font-family: 'Inter', sans-serif;
}
.modal-header {
@@ -462,6 +592,7 @@
padding: 25px 30px 15px;
border-radius: 20px 20px 0 0;
position: relative;
+ font-family: 'Inter', sans-serif;
}
.modal-header::after {
@@ -477,6 +608,7 @@
.modal-title {
font-weight: 700;
font-size: 1.5rem;
+ font-family: 'Inter', sans-serif;
}
.btn-close {
@@ -490,6 +622,7 @@
.modal-body {
padding: 25px 30px;
+ font-family: 'Inter', sans-serif;
}
/* Form Styles */
@@ -498,16 +631,18 @@
color: #5a6c7d;
margin-bottom: 8px;
font-size: 0.9rem;
+ font-family: 'Inter', sans-serif;
}
.form-control {
border-radius: 10px;
border: 1px solid #e2e8f0;
padding: 12px 16px;
- font-size: 15px;
+ font-size: 14px;
transition: all 0.3s ease;
background: #fafbfc;
color: #4a5568;
+ font-family: 'Inter', sans-serif;
}
.form-control:focus {
@@ -520,39 +655,6 @@
color: #a0aec0;
}
- /* Date Input Styling */
- input[type="date"] {
- position: relative;
- }
-
- input[type="date"]::-webkit-calendar-picker-indicator {
- background: transparent;
- bottom: 0;
- color: transparent;
- cursor: pointer;
- height: auto;
- left: 0;
- position: absolute;
- right: 0;
- top: 0;
- width: auto;
- }
-
- input[type="date"] {
- position: relative;
- padding-right: 40px;
- }
-
- input[type="date"]:after {
- content: "📅";
- position: absolute;
- right: 12px;
- top: 50%;
- transform: translateY(-50%);
- pointer-events: none;
- font-size: 16px;
- }
-
/* Button Styles */
.btn-cancel {
background: #f7fafc;
@@ -562,6 +664,8 @@
font-weight: 600;
padding: 12px 30px;
transition: all 0.3s ease;
+ font-family: 'Inter', sans-serif;
+ font-size: 14px;
}
.btn-cancel:hover {
@@ -575,11 +679,12 @@
background: linear-gradient(135deg, #48bb78, #38a169);
color: white;
font-weight: 600;
- font-size: 16px;
+ font-size: 14px;
border-radius: 10px;
padding: 12px 35px;
border: none;
transition: all 0.3s ease;
+ font-family: 'Inter', sans-serif;
}
.btn-create:hover {
@@ -595,6 +700,7 @@
border-spacing: 0 8px;
margin: 0;
min-width: 1300px;
+ font-family: 'Inter', sans-serif;
}
.custom-table-modal thead th {
@@ -605,9 +711,10 @@
border: 1px solid #e2e8f0;
text-align: center;
position: relative;
- font-size: 0.9rem;
+ font-size: 14px;
letter-spacing: 0.3px;
white-space: nowrap;
+ font-family: 'Inter', sans-serif;
}
.custom-table-modal thead th:first-child {
@@ -644,6 +751,8 @@
position: relative;
color: #4a5568;
white-space: nowrap;
+ font-family: 'Inter', sans-serif;
+ font-size: 14px;
}
.custom-table-modal tbody tr td:first-child {
@@ -656,38 +765,6 @@
border-bottom-right-radius: 10px;
}
- /* Checkbox Styling */
- input[type="checkbox"] {
- width: 20px;
- height: 20px;
- border-radius: 6px;
- border: 2px solid #cbd5e0;
- cursor: pointer;
- position: relative;
- transition: all 0.2s ease;
- background: #f7fafc;
- }
-
- input[type="checkbox"]:checked {
- background: var(--primary);
- border-color: var(--primary);
- }
-
- /* Link Styling */
- a.text-primary {
- color: var(--primary) !important;
- text-decoration: none;
- font-weight: 600;
- transition: all 0.3s ease;
- position: relative;
- color: #4361ee !important;
- }
-
- a.text-primary:hover {
- color: var(--primary-dark) !important;
- text-decoration: underline;
- }
-
/* Shipment Details Modal */
.shipment-details-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
@@ -695,10 +772,12 @@
border: none;
padding: 25px 30px 15px;
border-radius: 20px 20px 0 0;
+ font-family: 'Inter', sans-serif;
}
.shipment-details-body {
padding: 40px 45px;
+ font-family: 'Inter', sans-serif;
}
.shipment-info-row {
@@ -709,6 +788,7 @@
background: #f8fafc;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
+ font-family: 'Inter', sans-serif;
}
.shipment-info-item {
@@ -722,12 +802,14 @@
color: #64748b;
font-size: 14px;
margin-bottom: 5px;
+ font-family: 'Inter', sans-serif;
}
.shipment-info-value {
font-weight: 700;
font-size: 18px;
color: var(--dark);
+ font-family: 'Inter', sans-serif;
}
.shipment-details-table {
@@ -736,6 +818,7 @@
border-spacing: 0 8px;
margin-top: 20px;
min-width: 1400px;
+ font-family: 'Inter', sans-serif;
}
.shipment-details-table th {
@@ -747,6 +830,8 @@
border: none;
position: relative;
white-space: nowrap;
+ font-family: 'Inter', sans-serif;
+ font-size: 14px;
}
.shipment-details-table th:first-child {
@@ -766,6 +851,8 @@
background: white;
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
white-space: nowrap;
+ font-family: 'Inter', sans-serif;
+ font-size: 14px;
}
.shipment-details-table tr td:first-child {
@@ -778,6 +865,31 @@
border-bottom-right-radius: 10px;
}
+ /* Delete Button for Orders */
+ .btn-delete-order {
+ background: linear-gradient(135deg, #f87171, #ef4444);
+ color: white;
+ border: none;
+ border-radius: 6px;
+ padding: 6px 12px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ font-size: 12px;
+ font-weight: 600;
+ font-family: 'Inter', sans-serif;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 80px;
+ justify-content: center;
+ }
+
+ .btn-delete-order:hover {
+ background: linear-gradient(135deg, #ef4444, #dc2626);
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
+ }
+
/* Shipment Totals Section */
.shipment-totals {
margin-top: 25px;
@@ -786,6 +898,7 @@
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0,0,0,0.05);
border-left: 4px solid #4361ee;
+ font-family: 'Inter', sans-serif;
}
.shipment-totals-row {
@@ -812,6 +925,7 @@
margin-bottom: 8px;
text-transform: uppercase;
letter-spacing: 0.5px;
+ font-family: 'Inter', sans-serif;
}
.shipment-total-value {
@@ -819,6 +933,7 @@
font-size: 20px;
color: #1e293b;
line-height: 1.2;
+ font-family: 'Inter', sans-serif;
}
.total-amount {
@@ -891,6 +1006,7 @@
/* Status Filter Styles */
.status-filter-container {
position: relative;
+ margin-left:350px;
}
.status-filter-select {
@@ -905,17 +1021,189 @@
padding-right: 40px !important;
}
- /* Shipment row styling for filtering */
- .shipment-row {
+ /* Pagination Styles */
+ .pagination-container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-top: 15px;
+ padding: 12px 25px;
+ border-top: 1px solid #eef3fb;
+ font-family: 'Inter', sans-serif;
+ }
+
+ .pagination-info {
+ font-size: 13px;
+ color: #9ba5bb;
+ font-weight: 600;
+ font-family: 'Inter', sans-serif;
+ }
+
+ .pagination-controls {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ }
+
+ .pagination-btn {
+ background: #fff;
+ border: 1px solid #e3eaf6;
+ color: #1a2951;
+ padding: 8px 12px;
+ border-radius: 6px;
+ font-size: 13px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 40px;
+ height: 32px;
+ font-family: 'Inter', sans-serif;
+ }
+
+ .pagination-btn:hover:not(:disabled) {
+ background: #1a2951;
+ color: white;
+ border-color: #1a2951;
+ }
+
+ .pagination-btn:disabled {
+ background: #f8fafc;
+ color: #cbd5e0;
+ border-color: #e2e8f0;
+ cursor: not-allowed;
+ opacity: 0.6;
+ }
+
+ .pagination-page-btn {
+ background: #fff;
+ border: 1px solid #e3eaf6;
+ color: #1a2951;
+ padding: 6px 12px;
+ border-radius: 6px;
+ font-size: 13px;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ min-width: 36px;
+ text-align: center;
+ font-family: 'Inter', sans-serif;
+ }
+
+ .pagination-page-btn:hover {
+ background: #1a2951;
+ color: white;
+ border-color: #1a2951;
+ }
+
+ .pagination-page-btn.active {
+ background: #1a2951;
+ color: white;
+ border-color: #1a2951;
+ }
+
+ .pagination-pages {
+ display: flex;
+ gap: 4px;
+ align-items: center;
+ }
+
+ .pagination-ellipsis {
+ color: #9ba5bb;
+ font-size: 13px;
+ padding: 0 4px;
+ font-family: 'Inter', sans-serif;
+ }
+
+ .pagination-img-btn {
+ background: #fff;
+ border: 1px solid #e3eaf6;
+ border-radius: 6px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 40px;
+ height: 32px;
+ padding: 0;
+ }
+
+ .pagination-img-btn:hover:not(:disabled) {
+ background: #1a2951;
+ border-color: #1a2951;
+ }
+
+ .pagination-img-btn:disabled {
+ background: #f8fafc;
+ border-color: #e2e8f0;
+ cursor: not-allowed;
+ opacity: 0.5;
+ }
+
+ .pagination-img-btn img {
+ width: 16px;
+ height: 16px;
+ filter: brightness(0) saturate(100%) invert(26%) sepia(89%) saturate(748%) hue-rotate(201deg) brightness(93%) contrast(89%);
+ transition: filter 0.3s ease;
+ }
+
+ .pagination-img-btn:hover:not(:disabled) img {
+ filter: brightness(0) saturate(100%) invert(100%) sepia(100%) saturate(0%) hue-rotate(288deg) brightness(106%) contrast(101%);
+ }
+
+ .pagination-img-btn:disabled img {
+ filter: brightness(0) saturate(100%) invert(84%) sepia(8%) saturate(165%) hue-rotate(179deg) brightness(89%) contrast(86%);
+ }
+
+ @media (max-width: 768px) {
+ .pagination-container {
+ flex-direction: column;
+ gap: 10px;
+ align-items: stretch;
+ }
+
+ .pagination-controls {
+ justify-content: center;
+ }
+ }
+
+ /* Delete Confirmation Modal */
+ .delete-confirmation-modal .modal-header {
+ background: linear-gradient(135deg, #ef4444, #dc2626);
+ }
+
+ .delete-confirmation-modal .btn-confirm-delete {
+ background: linear-gradient(135deg, #ef4444, #dc2626);
+ color: white;
+ border: none;
+ border-radius: 8px;
+ padding: 10px 20px;
+ font-weight: 600;
transition: all 0.3s ease;
}
- .shipment-row.hidden {
- display: none !important;
+ .delete-confirmation-modal .btn-confirm-delete:hover {
+ background: linear-gradient(135deg, #dc2626, #b91c1c);
+ transform: translateY(-2px);
+ box-shadow: 0 4px 12px rgba(220, 38, 38, 0.3);
}
- .shipment-row.visible {
- display: table-row;
+ .delete-confirmation-modal .btn-cancel-delete {
+ background: #f7fafc;
+ color: #718096;
+ border: 1px solid #cbd5e0;
+ border-radius: 8px;
+ padding: 10px 20px;
+ font-weight: 600;
+ transition: all 0.3s ease;
+ }
+
+ .delete-confirmation-modal .btn-cancel-delete:hover {
+ background: #edf2f7;
+ color: #4a5568;
}
@@ -938,12 +1226,27 @@
@endif
-
-
-
+
-
🔍
-
+
+
+
+
+
+
+
+
+
All Status
@@ -953,21 +1256,13 @@
Delivered
-
- All Carriers
- FedEx
- UPS
- DHL
-
🚚
Add Shipments
-
-
-
+