diff --git a/app/Http/Controllers/Admin/AdminInvoiceController.php b/app/Http/Controllers/Admin/AdminInvoiceController.php index 62cb0fe..b88b4d6 100644 --- a/app/Http/Controllers/Admin/AdminInvoiceController.php +++ b/app/Http/Controllers/Admin/AdminInvoiceController.php @@ -10,9 +10,6 @@ use Mpdf\Mpdf; use App\Models\InvoiceInstallment; use Illuminate\Support\Facades\Log; - - - class AdminInvoiceController extends Controller { // ------------------------------------------------------------- @@ -27,7 +24,7 @@ class AdminInvoiceController extends Controller // ------------------------------------------------------------- // POPUP VIEW (AJAX) // ------------------------------------------------------------- - public function popup($id) + public function popup($id) { $invoice = Invoice::with(['items', 'order'])->findOrFail($id); @@ -40,14 +37,12 @@ class AdminInvoiceController extends Controller return view('admin.popup_invoice', compact('invoice', 'shipment')); } - // ------------------------------------------------------------- // EDIT INVOICE PAGE // ------------------------------------------------------------- public function edit($id) { $invoice = Invoice::with(['order.shipments'])->findOrFail($id); - $shipment = $invoice->order?->shipments?->first(); return view('admin.invoice_edit', compact('invoice', 'shipment')); @@ -56,95 +51,82 @@ class AdminInvoiceController extends Controller // ------------------------------------------------------------- // UPDATE INVOICE // ------------------------------------------------------------- + public function update(Request $request, $id) + { + Log::info("🟡 Invoice Update Request Received", [ + 'invoice_id' => $id, + 'request' => $request->all() + ]); -public function update(Request $request, $id) -{ - Log::info("🟡 Invoice Update Request Received", [ - 'invoice_id' => $id, - 'request' => $request->all() - ]); + $invoice = Invoice::findOrFail($id); - $invoice = Invoice::findOrFail($id); + $data = $request->validate([ + 'invoice_date' => 'required|date', + 'due_date' => 'required|date|after_or_equal:invoice_date', + 'final_amount' => 'required|numeric|min:0', + 'tax_type' => 'required|in:gst,igst', + 'tax_percent' => 'required|numeric|min:0|max:28', + 'status' => 'required|in:pending,paid,overdue', + 'notes' => 'nullable|string', + ]); - $data = $request->validate([ - 'invoice_date' => 'required|date', - 'due_date' => 'required|date|after_or_equal:invoice_date', - 'final_amount' => 'required|numeric|min:0', - 'tax_type' => 'required|in:gst,igst', - 'tax_percent' => 'required|numeric|min:0|max:28', - 'status' => 'required|in:pending,paid,overdue', - 'notes' => 'nullable|string', - ]); + Log::info("✅ Validated Invoice Update Data", $data); - Log::info("✅ Validated Invoice Update Data", $data); + $finalAmount = floatval($data['final_amount']); + $taxPercent = floatval($data['tax_percent']); + $taxAmount = 0; - $finalAmount = floatval($data['final_amount']); - $taxPercent = floatval($data['tax_percent']); - $taxAmount = 0; + if ($data['tax_type'] === 'gst') { + Log::info("🟢 GST Selected", compact('taxPercent')); + $data['cgst_percent'] = $taxPercent / 2; + $data['sgst_percent'] = $taxPercent / 2; + $data['igst_percent'] = 0; + } else { + Log::info("🔵 IGST Selected", compact('taxPercent')); + $data['cgst_percent'] = 0; + $data['sgst_percent'] = 0; + $data['igst_percent'] = $taxPercent; + } - if ($data['tax_type'] === 'gst') { - Log::info("🟢 GST Selected", compact('taxPercent')); + $taxAmount = ($finalAmount * $taxPercent) / 100; - $data['cgst_percent'] = $taxPercent / 2; - $data['sgst_percent'] = $taxPercent / 2; - $data['igst_percent'] = 0; - } else { - Log::info("🔵 IGST Selected", compact('taxPercent')); + $data['gst_amount'] = $taxAmount; + $data['final_amount_with_gst'] = $finalAmount + $taxAmount; + $data['gst_percent'] = $taxPercent; - $data['cgst_percent'] = 0; - $data['sgst_percent'] = 0; - $data['igst_percent'] = $taxPercent; + Log::info("📌 Final Calculated Invoice Values", [ + 'invoice_id' => $invoice->id, + 'final_amount' => $finalAmount, + 'gst_amount' => $data['gst_amount'], + 'final_amount_with_gst' => $data['final_amount_with_gst'], + 'tax_type' => $data['tax_type'], + 'cgst_percent' => $data['cgst_percent'], + 'sgst_percent' => $data['sgst_percent'], + 'igst_percent' => $data['igst_percent'], + ]); + + $invoice->update($data); + + Log::info("✅ Invoice Updated Successfully", [ + 'invoice_id' => $invoice->id + ]); + + // regenerate PDF + $this->generateInvoicePDF($invoice); + + return redirect() + ->route('admin.invoices.index') + ->with('success', 'Invoice updated & PDF generated successfully.'); } - $taxAmount = ($finalAmount * $taxPercent) / 100; - - $data['gst_amount'] = $taxAmount; - $data['final_amount_with_gst'] = $finalAmount + $taxAmount; - - // ✅ store original % for UI reference - $data['gst_percent'] = $taxPercent; - - Log::info("📌 Final Calculated Invoice Values", [ - 'invoice_id' => $invoice->id, - 'final_amount' => $finalAmount, - 'gst_amount' => $data['gst_amount'], - 'final_amount_with_gst' => $data['final_amount_with_gst'], - 'tax_type' => $data['tax_type'], - 'cgst_percent' => $data['cgst_percent'], - 'sgst_percent' => $data['sgst_percent'], - 'igst_percent' => $data['igst_percent'], - ]); - - $invoice->update($data); - - Log::info("✅ Invoice Updated Successfully", [ - 'invoice_id' => $invoice->id - ]); - - // regenerate PDF - $this->generateInvoicePDF($invoice); - - return redirect() - ->route('admin.invoices.index') - ->with('success', 'Invoice updated & PDF generated successfully.'); -} - - // ------------------------------------------------------------- // PDF GENERATION USING mPDF // ------------------------------------------------------------- public function generateInvoicePDF($invoice) { - // Load relationship including shipment $invoice->load(['items', 'order.shipments']); - - // Fetch shipment $shipment = $invoice->order?->shipments?->first(); - - // PDF filename $fileName = 'invoice-' . $invoice->invoice_number . '.pdf'; - - // Directory path $folder = public_path('invoices/'); if (!file_exists($folder)) { @@ -152,110 +134,94 @@ public function update(Request $request, $id) } $filePath = $folder . $fileName; - - // Delete old file if exists if (file_exists($filePath)) { unlink($filePath); } - // Create mPDF instance - $mpdf = new Mpdf([ - 'mode' => 'utf-8', - 'format' => 'A4', - 'default_font' => 'sans-serif', - ]); - - // Load HTML view - $html = view('admin.pdf.invoice', [ - 'invoice' => $invoice, - 'shipment' => $shipment - ])->render(); - - // Write HTML to PDF + $mpdf = new Mpdf(['mode' => 'utf-8', 'format' => 'A4', 'default_font' => 'sans-serif']); + $html = view('admin.pdf.invoice', ['invoice' => $invoice, 'shipment' => $shipment])->render(); $mpdf->WriteHTML($html); - - // Save PDF $mpdf->Output($filePath, 'F'); + $invoice->update(['pdf_path' => 'invoices/' . $fileName]); + } - // Update DB path - $invoice->update([ - 'pdf_path' => 'invoices/' . $fileName + // ------------------------------------------------------------- + // INSTALLMENTS (ADD/DELETE) + // ------------------------------------------------------------- + public function storeInstallment(Request $request, $invoice_id) + { + $request->validate([ + 'installment_date' => 'required|date', + 'payment_method' => 'required|string', + 'reference_no' => 'nullable|string', + 'amount' => 'required|numeric|min:1', + ]); + + $invoice = Invoice::findOrFail($invoice_id); + + $paidTotal = $invoice->installments()->sum('amount'); + // Use GST-inclusive total for all calculations/checks + $remaining = $invoice->final_amount_with_gst - $paidTotal; + + if ($request->amount > $remaining) { + return response()->json([ + 'status' => 'error', + 'message' => 'Installment amount exceeds remaining balance.' + ], 422); + } + + $installment = InvoiceInstallment::create([ + 'invoice_id' => $invoice_id, + 'installment_date' => $request->installment_date, + 'payment_method' => $request->payment_method, + 'reference_no' => $request->reference_no, + 'amount' => $request->amount, + ]); + + $newPaid = $paidTotal + $request->amount; + + // Mark as 'paid' if GST-inclusive total is cleared + if ($newPaid >= $invoice->final_amount_with_gst) { + $invoice->update(['status' => 'paid']); + } + + return response()->json([ + 'status' => 'success', + 'message' => 'Installment added successfully.', + 'installment' => $installment, + 'totalPaid' => $newPaid, + 'gstAmount' => $invoice->gst_amount, + 'finalAmountWithGst' => $invoice->final_amount_with_gst, + 'baseAmount' => $invoice->final_amount, + 'remaining' => max(0, $invoice->final_amount_with_gst - $newPaid), + 'isCompleted' => $newPaid >= $invoice->final_amount_with_gst ]); } - - - -public function storeInstallment(Request $request, $invoice_id) -{ - $request->validate([ - 'installment_date' => 'required|date', - 'payment_method' => 'required|string', - 'reference_no' => 'nullable|string', - 'amount' => 'required|numeric|min:1', - ]); - - $invoice = Invoice::findOrFail($invoice_id); - - $paidTotal = $invoice->installments()->sum('amount'); - $remaining = $invoice->final_amount - $paidTotal; - - if ($request->amount > $remaining) { + public function deleteInstallment($id) + { + $installment = InvoiceInstallment::findOrFail($id); + $invoice = $installment->invoice; + + $installment->delete(); + + $paidTotal = $invoice->installments()->sum('amount'); + $remaining = $invoice->final_amount_with_gst - $paidTotal; + + // Update status if not fully paid anymore + if ($remaining > 0 && $invoice->status === "paid") { + $invoice->update(['status' => 'pending']); + } + return response()->json([ - 'status' => 'error', - 'message' => 'Installment amount exceeds remaining balance.' - ], 422); + 'status' => 'success', + 'message' => 'Installment deleted.', + 'totalPaid' => $paidTotal, + 'gstAmount' => $invoice->gst_amount, + 'finalAmountWithGst' => $invoice->final_amount_with_gst, + 'baseAmount' => $invoice->final_amount, + 'remaining' => $remaining, + 'isZero' => $paidTotal == 0 + ]); } - - $installment = InvoiceInstallment::create([ - 'invoice_id' => $invoice_id, - 'installment_date' => $request->installment_date, - 'payment_method' => $request->payment_method, - 'reference_no' => $request->reference_no, - 'amount' => $request->amount, - ]); - - // Update invoice status to paid if fully cleared - $newPaid = $paidTotal + $request->amount; - - if ($newPaid >= $invoice->final_amount) { - $invoice->update(['status' => 'paid']); - } - - return response()->json([ - 'status' => 'success', - 'message' => 'Installment added successfully.', - 'installment' => $installment, - 'totalPaid' => $newPaid, - 'remaining' => max(0, $invoice->final_amount - $newPaid), - 'isCompleted' => $newPaid >= $invoice->final_amount - ]); -} - -public function deleteInstallment($id) -{ - $installment = InvoiceInstallment::findOrFail($id); - $invoice = $installment->invoice; - - // delete installment - $installment->delete(); - - // recalc totals - $paidTotal = $invoice->installments()->sum('amount'); - $remaining = $invoice->final_amount - $paidTotal; - - // auto update invoice status - if ($remaining > 0 && $invoice->status === "paid") { - $invoice->update(['status' => 'pending']); - } - - return response()->json([ - 'status' => 'success', - 'message' => 'Installment deleted.', - 'totalPaid' => $paidTotal, - 'remaining' => $remaining, - 'isZero' => $paidTotal == 0 - ]); -} - - + } diff --git a/app/Http/Controllers/Admin/AdminOrderController.php b/app/Http/Controllers/Admin/AdminOrderController.php index 6dadb27..47a1da3 100644 --- a/app/Http/Controllers/Admin/AdminOrderController.php +++ b/app/Http/Controllers/Admin/AdminOrderController.php @@ -297,4 +297,17 @@ class AdminOrderController extends Controller ->with('success', 'Order reset successfully.'); } + public function orderShow() + { + $orders = Order::with([ + 'markList', // company, customer, origin, destination, date + 'shipments', // shipment_id, shipment_date, status + 'invoice' // invoice number, dates, amounts, status + ]) + ->latest('id') // show latest orders first + ->get(); + + return view('admin.orders', compact('orders')); + } + } diff --git a/app/Http/Controllers/RequestController.php b/app/Http/Controllers/RequestController.php index e6af629..685271c 100644 --- a/app/Http/Controllers/RequestController.php +++ b/app/Http/Controllers/RequestController.php @@ -53,4 +53,6 @@ class RequestController extends Controller 'data' => $newRequest ]); } + + } diff --git a/app/Models/Order.php b/app/Models/Order.php index c1ce73c..d3691c8 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -56,5 +56,11 @@ class Order extends Model return $this->belongsToMany(\App\Models\Shipment::class, 'shipment_items', 'order_id', 'shipment_id'); } + public function invoice() + { + return $this->hasOne(\App\Models\Invoice::class, 'order_id', 'id'); + } + + } diff --git a/public/invoices/invoice-INV-2025-000020.pdf b/public/invoices/invoice-INV-2025-000020.pdf new file mode 100644 index 0000000..89c69e8 Binary files /dev/null and b/public/invoices/invoice-INV-2025-000020.pdf differ diff --git a/public/invoices/invoice-INV-2025-000024.pdf b/public/invoices/invoice-INV-2025-000024.pdf new file mode 100644 index 0000000..d02fe9e Binary files /dev/null and b/public/invoices/invoice-INV-2025-000024.pdf differ diff --git a/public/invoices/invoice-INV-2025-000025.pdf b/public/invoices/invoice-INV-2025-000025.pdf new file mode 100644 index 0000000..29b973e Binary files /dev/null and b/public/invoices/invoice-INV-2025-000025.pdf differ diff --git a/resources/views/admin/account.blade.php b/resources/views/admin/account.blade.php index 768db26..454de4c 100644 --- a/resources/views/admin/account.blade.php +++ b/resources/views/admin/account.blade.php @@ -29,7 +29,7 @@ body { /* container */ .account-container { padding: 28px 34px; - max-width:1300px; + max-width:1400px; margin: 18px auto; box-sizing:border-box; } @@ -70,29 +70,128 @@ body { .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; flex-wrap:wrap; } +.account-panels { + display:flex; + gap:22px; + align-items:flex-start; + flex-wrap:wrap; +} .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:18px; box-sizing:border-box; overflow-x:auto; transition: transform .12s, box-shadow .12s; + 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; + display: flex; + flex-direction: column; } .panel-card:hover{ transform: translateY(-4px); box-shadow:0 12px 28px rgba(25,40,80,0.08); } -.panel-title { font-weight:700; font-size:16px; color:var(--primary-1); margin-bottom:12px; display:flex; align-items:center; justify-content:space-between; } +.panel-title { + font-weight:700; + font-size:16px; + color:var(--primary-1); + margin-bottom:16px; + display:flex; + align-items:center; + justify-content:space-between; +} /* table */ -table { width:100%; border-collapse:collapse; min-width:720px; font-size:14px; } -th, td { padding:10px 12px; text-align:left; border-bottom:1px solid #eef3fb; white-space:nowrap; color:#2d3b53; } -th { background: linear-gradient(90deg,#f6f9ff,#fbfdff); color:#4a5570; font-weight:700; font-size:13px; } +table { + width:100%; + border-collapse:collapse; + min-width:720px; + font-size:14px; + flex:1; +} +th, td { + padding:12px 14px; + text-align:left; + border-bottom:1px solid #eef3fb; + white-space:nowrap; + color:#2d3b53; +} +th { + background: linear-gradient(90deg,#f6f9ff,#fbfdff); + color:#4a5570; + font-weight:700; + font-size:13px; +} tr:hover td{ background:#fbfdff; } .entry-link{ color:var(--accent); text-decoration:underline; cursor:pointer; font-weight:700; } /* badges */ -.status-badge { display:inline-block; padding:6px 12px; border-radius:20px; color:#fff; font-size:13px; font-weight:600; } -.status-unpaid{ background:var(--danger); } -.status-paid{ background:var(--success); } -.status-loading{ background:#509cf8; } -.status-dispatched{ background:#20c5c7; } -.pending-badge-red{ background:var(--danger); } -.pending-badge-green{ background:var(--success); } + +/* === Modern Status Badges === */ +.status-badge { + display: inline-block; + padding: 6px 16px; + border-radius: 999px; + font-size: 13px; + font-weight: 700; + color: #fff; + min-width: 76px; + text-align: center; + box-shadow: 0 2px 8px rgba(33, 43, 90, 0.07); + letter-spacing: 0.1px; + background: #6b7280; /* fallback */ + 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; +} + +.status-badge:hover { + transform: translateY(-3px) scale(1.045); + box-shadow: 0 4px 16px rgba(33, 43, 90, 0.16); + opacity: 0.96; +} + +/* High-impact, soft gradients for each status */ +.status-unpaid { + background: linear-gradient(90deg, #ff5959, #dc3545); + border: 1.5px solid #d42c3f21; + width: 95px; +} +.status-paid { + background: linear-gradient(90deg, #36d399 0%, #4ade80 100%); + border: 1.5px solid #31b47a1a; + width: 95px; +} +.status-loading { + background: linear-gradient(90deg, #509cf8 0%, #3f79d3 100%); + border: 1.5px solid #1665c320; + width: 95px; +} +.status-dispatched { + background: linear-gradient(90deg, #9775fa 0%, #845ef7 100%); + border: 1.5px solid #9775fa40; + width: 95px; +} +.pending-badge-red { + background: linear-gradient(90deg, #f43f5e, #ef4444); + border: 1.5px solid #f43f5e41; + width: 95px; +} +.pending-badge-green { + background: linear-gradient(90deg, #10b981 0%, #22d3ee 100%); + border: 1.5px solid #10b98141; + width: 95px; +} + +.status-delivered { + background: linear-gradient(90deg, #22c55e 0%, #16a34a 100%); + border: 1.5px solid #22c55e44; + width: 95px; +} /* 3-state toggle */ .toggle-switch-btn { @@ -140,48 +239,237 @@ tr:hover td{ background:#fbfdff; } transform: translateX(38px); } - /* plus button */ -.plus-btn { display:inline-block; width:36px; height:36px; border-radius:10px; background:#fff; color:var(--primary-1); border:1.5px solid #e6edf8; font-size:1.15rem; font-weight:700; text-align:center; line-height:34px; cursor:pointer; transition: transform .12s; } +.plus-btn { + display:inline-block; + width:36px; + height:36px; + border-radius:10px; + background:#fff; + color:var(--primary-1); + border:1.5px solid #e6edf8; + font-size:1.15rem; + font-weight:700; + text-align:center; + line-height:34px; + cursor:pointer; + transition: transform .12s; +} .plus-btn:hover{ transform: translateY(-3px); box-shadow:0 8px 16px rgba(33,47,90,0.04); } -/* ---------- Expandable Create Order Card (Option D) ---------- */ -.create-card { - margin: 10px 0 18px 0; - border-radius: 12px; - background: linear-gradient(180deg,#ffffff,#fbfdff); - box-shadow:0 10px 30px rgba(20,40,80,0.04); - overflow: hidden; transition: max-height .28s ease, padding .22s ease; - max-height: 0; padding: 0 18px; opacity:0; pointer-events:none; +/* ---------- Create Order Popup Modal ---------- */ +.create-order-modal { + position:fixed; + inset:0; + background:rgba(16,24,50,0.44); + display:none; + align-items:center; + justify-content:center; + z-index:1200; + padding:18px; +} +.create-order-modal.modal-open { display:flex; } +.create-order-modal .modal-box { + background:#fff; + border-radius:12px; + padding:20px 24px; + box-shadow:0 14px 40px rgba(18,30,60,0.12); + max-width:1200px; + width:100%; + max-height:92vh; + overflow:auto; } -.create-card.open { max-height: 1500px; padding: 18px; opacity:1; pointer-events:auto; } -.create-card .create-inner { display:flex; gap:14px; flex-direction:column; } -.create-card .create-grid { display:grid; grid-template-columns: 1fr 1fr; gap:12px; align-items:start; } -.create-card label{ font-weight:700; color:#28384f; margin-bottom:6px; font-size:13px; } -.input, select { width:100%; padding:10px 12px; border-radius:8px; border:1.3px solid #e3eaf6; background:#fff; font-size:14px; box-sizing:border-box; } -.create-actions { display:flex; gap:10px; justify-content:flex-end; margin-top:12px; } /* consolidated orders area */ .consolidate-area { background: linear-gradient(90deg,#fbfbff,#f9fcff); - border:1px solid #eef5ff; padding:10px; border-radius:10px; box-shadow: inset 0 1px 0 rgba(255,255,255,0.6); - margin-top:8px; overflow:auto; + border:1px solid #eef5ff; + padding:14px; + border-radius:10px; + box-shadow: inset 0 1px 0 rgba(255,255,255,0.6); + margin-top:12px; + overflow:auto; + min-height: 400px; + display: flex; + flex-direction: column; } -.consolidate-toggle { display:flex; gap:10px; align-items:center; margin-bottom:8px; } -.consolidate-tab-btn { background:#fff; border:1px solid #e6edf9; padding:8px 10px; border-radius:8px; font-weight:700; cursor:pointer; } -.consolidate-tab-btn.active { background:linear-gradient(90deg,var(--primary-1),var(--primary-2)); color:#fff; border-color:transparent; box-shadow:0 6px 18px rgba(36,58,114,0.08); } /* compact table in consolidate */ -#consolidateOrdersTable th, #consolidateOrdersTable td { padding:8px 9px; font-size:13px; border-bottom:1px solid #f1f6ff; } +#consolidateOrdersTable th, #consolidateOrdersTable td { padding:10px 12px; font-size:13px; border-bottom:1px solid #f1f6ff; } + +/* ---------- Pagination Styles ---------- */ +.pagination-container { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 15px; + padding: 12px 0; + border-top: 1px solid #eef3fb; +} + +.pagination-info { + font-size: 13px; + color: var(--muted); + font-weight: 600; +} + +.pagination-controls { + display: flex; + align-items: center; + gap: 8px; +} + +.pagination-btn { + background: #fff; + border: 1px solid #e3eaf6; + color: var(--primary-1); + 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; +} + +.pagination-btn:hover:not(:disabled) { + background: var(--primary-1); + color: white; + border-color: var(--primary-1); +} + +.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: var(--primary-1); + 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; +} + +.pagination-page-btn:hover { + background: var(--primary-1); + color: white; + border-color: var(--primary-1); +} + +.pagination-page-btn.active { + background: var(--primary-1); + color: white; + border-color: var(--primary-1); +} + +.pagination-pages { + display: flex; + gap: 4px; + align-items: center; +} + +.pagination-ellipsis { + color: var(--muted); + font-size: 13px; + padding: 0 4px; +} + +/* Image-based pagination buttons */ +.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: var(--primary-1); + border-color: var(--primary-1); +} + +.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%); +} /* ---------- Entry Details Modal (existing) ---------- */ -.modal-fade1 { position:fixed; inset:0; background:rgba(16,24,50,0.44); display:none; align-items:center; justify-content:center; z-index:1200; padding:18px; } +.modal-fade1 { + position:fixed; + inset:0; + background:rgba(16,24,50,0.44); + display:none; + align-items:center; + justify-content:center; + z-index:1200; + padding:18px; +} .modal-fade1.modal-open { display:flex; } -.modal-box1 { background:#fff; border-radius:12px; padding:16px 18px; box-shadow:0 14px 40px rgba(18,30,60,0.12); max-width:1100px; width:100%; max-height:92vh; overflow:auto; } +.modal-box1 { + background:#fff; + border-radius:12px; + padding:20px 24px; + box-shadow:0 14px 40px rgba(18,30,60,0.12); + max-width:1200px; + width:100%; + max-height:92vh; + overflow:auto; + min-height: 500px; +} /* entry summary cards */ -.entry-summary-cards { display:flex; gap:12px; margin-bottom:14px; flex-wrap:wrap; } -.entry-summary-card { background:#fbfdff; border:1px solid #eef6ff; padding:12px; border-radius:10px; min-width:160px; box-shadow:0 6px 18px rgba(22,36,72,0.03); } +.entry-summary-cards { + display:flex; + gap:16px; + margin-bottom:20px; + flex-wrap:wrap; +} +.entry-summary-card { + background:#fbfdff; + border:1px solid #eef6ff; + padding:16px; + border-radius:10px; + min-width:180px; + box-shadow:0 6px 18px rgba(22,36,72,0.03); + flex:1; +} .entry-summary-label{ font-size:12px; color:var(--muted); } .entry-summary-value{ font-size:18px; font-weight:700; color:#253047; margin-top:6px; } @@ -193,11 +481,47 @@ tr:hover td{ background:#fbfdff; } .empty-state{ padding:18px; text-align:center; color:#6f7b8f; } .kv { font-weight:700; color:#26364f; } +/* form styles */ +.input, select { + width:100%; + padding:12px 14px; + border-radius:8px; + border:1.3px solid #e3eaf6; + background:#fff; + font-size:14px; + box-sizing:border-box; +} +.create-grid { + display:grid; + grid-template-columns: 1fr 1fr; + gap:16px; + align-items:start; + margin-bottom:16px; +} +.create-actions { + display:flex; + gap:12px; + justify-content:flex-end; + margin-top:16px; +} + /* responsive */ @media (max-width:980px){ - .create-card .create-grid { grid-template-columns: 1fr; } + .create-grid { grid-template-columns: 1fr; } .panel-card { min-width:100%; } .search-row input{ width:220px; } + .pagination-container { flex-direction: column; gap: 10px; align-items: stretch; } + .pagination-controls { justify-content: center; } + .account-container { padding: 20px; } + .panel-card { padding: 18px; } +} + +@media (max-width:768px){ + .account-header { padding: 18px; } + .top-actions { flex-direction: column; align-items: stretch; } + .top-actions .left { justify-content: center; } + .entry-summary-cards { gap: 12px; } + .entry-summary-card { min-width: 140px; } } @@ -216,7 +540,7 @@ tr:hover td{ background:#fbfdff; }
| Customer Info | -Customer ID | -Create Date | -Status | -Actions | -||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
-
-
- {{ strtoupper(substr($c->customer_name,0,1)) }}
+
+
+
+
+
+
|
+ ||||||||||||||||||
| + + No customers found. + | +||||||||||||||||||