conflict resolve

This commit is contained in:
divya abdar
2025-12-03 16:13:37 +05:30
23 changed files with 1634 additions and 629 deletions

View File

@@ -0,0 +1,98 @@
<?php
namespace App\Exports;
use App\Models\Order;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
class OrdersExport implements FromCollection, WithHeadings
{
protected $request;
public function __construct(Request $request)
{
$this->request = $request;
}
private function buildQuery()
{
$query = Order::with(['markList', 'invoice', 'shipments']);
if ($this->request->filled('search')) {
$search = $this->request->search;
$query->where(function($q) use ($search) {
$q->where('order_id', 'like', "%{$search}%")
->orWhereHas('markList', function($q2) use ($search) {
$q2->where('company_name', 'like', "%{$search}%")
->orWhere('customer_id', 'like', "%{$search}%");
})
->orWhereHas('invoice', function($q3) use ($search) {
$q3->where('invoice_number', 'like', "%{$search}%");
});
});
}
if ($this->request->filled('status')) {
$query->whereHas('invoice', function($q) {
$q->where('status', $this->request->status);
});
}
if ($this->request->filled('shipment')) {
$query->whereHas('shipments', function($q) {
$q->where('status', $this->request->shipment);
});
}
return $query->latest('id');
}
public function collection()
{
$orders = $this->buildQuery()->get();
// Map to simple array rows suitable for Excel
return $orders->map(function($order) {
$mark = $order->markList;
$invoice = $order->invoice;
$shipment = $order->shipments->first() ?? null;
return [
'Order ID' => $order->order_id,
'Shipment ID' => $shipment->shipment_id ?? '-',
'Customer ID' => $mark->customer_id ?? '-',
'Company' => $mark->company_name ?? '-',
'Origin' => $mark->origin ?? $order->origin ?? '-',
'Destination' => $mark->destination ?? $order->destination ?? '-',
'Order Date' => $order->created_at ? $order->created_at->format('d-m-Y') : '-',
'Invoice No' => $invoice->invoice_number ?? '-',
'Invoice Date' => $invoice?->invoice_date ? \Carbon\Carbon::parse($invoice->invoice_date)->format('d-m-Y') : '-',
'Amount' => $invoice?->final_amount ? number_format($invoice->final_amount, 2) : '-',
'Amount + GST' => $invoice?->final_amount_with_gst ? number_format($invoice->final_amount_with_gst, 2) : '-',
'Invoice Status' => $invoice->status ? ucfirst($invoice->status) : 'Pending',
'Shipment Status' => $shipment?->status ? ucfirst(str_replace('_', ' ', $shipment->status)) : 'Pending',
];
});
}
public function headings(): array
{
return [
'Order ID',
'Shipment ID',
'Customer ID',
'Company',
'Origin',
'Destination',
'Order Date',
'Invoice No',
'Invoice Date',
'Amount',
'Amount + GST',
'Invoice Status',
'Shipment Status',
];
}
}

View File

@@ -10,6 +10,10 @@ use App\Models\MarkList;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\InvoiceItem; use App\Models\InvoiceItem;
use App\Models\User; use App\Models\User;
use PDF; // barryvdh/laravel-dompdf facade
use Maatwebsite\Excel\Facades\Excel;
use App\Exports\OrdersExport;
class AdminOrderController extends Controller class AdminOrderController extends Controller
{ {
@@ -87,8 +91,8 @@ class AdminOrderController extends Controller
'status' => 'pending', 'status' => 'pending',
]); ]);
// If you want to auto-create an invoice at order creation, uncomment: //If you want to auto-create an invoice at order creation, uncomment:
// $this->createInvoice($order); $this->createInvoice($order);
return redirect()->route('admin.orders.show', $order->id) return redirect()->route('admin.orders.show', $order->id)
->with('success', 'Order created successfully.'); ->with('success', 'Order created successfully.');
@@ -164,30 +168,46 @@ class AdminOrderController extends Controller
return redirect()->back()->with('success', 'Item deleted and totals updated.'); 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 // ORDER CRUD: update / destroy
// --------------------------- // ---------------------------
public function updateItem(Request $request, $id) public function update(Request $request, $id)
{ {
$item = OrderItem::findOrFail($id); $order = Order::findOrFail($id);
$item->update([ $data = $request->validate([
'description' => $request->description, 'mark_no' => 'required|string',
'ctn' => $request->ctn, 'origin' => 'nullable|string',
'qty' => $request->qty, 'destination' => 'nullable|string',
'ttl_qty' => $request->ttl_qty,
'unit' => $request->unit,
'price' => $request->price,
'ttl_amount' => $request->ttl_amount,
'cbm' => $request->cbm,
'ttl_cbm' => $request->ttl_cbm,
'kg' => $request->kg,
'ttl_kg' => $request->ttl_kg,
'shop_no' => $request->shop_no,
]); ]);
return back()->with('success', 'Item updated successfully!'); $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.');
} }
/** /**
@@ -325,10 +345,6 @@ class AdminOrderController extends Controller
return null; return null;
} }
// -------------------------------------------------------------------------
// Popup function
// -------------------------------------------------------------------------
public function popup($id) public function popup($id)
{ {
// Load order with items + markList // Load order with items + markList
@@ -342,27 +358,8 @@ class AdminOrderController extends Controller
return view('admin.popup', compact('order', 'user')); return view('admin.popup', compact('order', 'user'));
} }
// -------------------------------------------------------------------------
// Restore Item
// -------------------------------------------------------------------------
public function restoreItem($id)
{
$item = OrderItem::onlyTrashed()->findOrFail($id);
$item->restore();
if (request()->ajax()) {
return response()->json([
'status' => 'ok',
'message' => 'Item restored.'
]);
}
return back()->belongsTo(Order::class)->with('success', 'Item restored successfully.');
}
// -------------------------------------------------------------------------
// Reset temp
// -------------------------------------------------------------------------
public function resetTemp() public function resetTemp()
@@ -373,11 +370,6 @@ class AdminOrderController extends Controller
->with('success', 'Order reset successfully.'); ->with('success', 'Order reset successfully.');
} }
// -------------------------------------------------------------------------
// ORDER SHOW PAGE
// -------------------------------------------------------------------------
public function orderShow() public function orderShow()
{ {
$orders = Order::with([ $orders = Order::with([
@@ -391,55 +383,79 @@ class AdminOrderController extends Controller
return view('admin.orders', compact('orders')); return view('admin.orders', compact('orders'));
} }
//==================================================== // inside AdminOrderController
// Download Pdf
//================================================= private function buildOrdersQueryFromRequest(Request $request)
public function downloadPdf(Request $request) {
{
$query = Order::with(['markList', 'invoice', 'shipments']); $query = Order::with(['markList', 'invoice', 'shipments']);
// Apply filters // Search across order_id, markList.company_name, markList.customer_id, invoice.invoice_number
if ($request->has('search') && $request->search) { if ($request->filled('search')) {
$search = $request->search; $search = $request->search;
$query->where(function($q) use ($search) { $query->where(function($q) use ($search) {
$q->where('order_id', 'like', "%{$search}%") $q->where('order_id', 'like', "%{$search}%")
->orWhereHas('markList', function($q) use ($search) { ->orWhereHas('markList', function($q2) use ($search) {
$q->where('company_name', 'like', "%{$search}%"); $q2->where('company_name', 'like', "%{$search}%")
->orWhere('customer_id', 'like', "%{$search}%");
}) })
->orWhereHas('invoice', function($q) use ($search) { ->orWhereHas('invoice', function($q3) use ($search) {
$q->where('invoice_number', 'like', "%{$search}%"); $q3->where('invoice_number', 'like', "%{$search}%");
}); });
}); });
} }
if ($request->has('status') && $request->status) { // Invoice status filter
if ($request->filled('status')) {
$query->whereHas('invoice', function($q) use ($request) { $query->whereHas('invoice', function($q) use ($request) {
$q->where('status', $request->status); $q->where('status', $request->status);
}); });
} }
if ($request->has('shipment') && $request->shipment) { // Shipment status filter
if ($request->filled('shipment')) {
$query->whereHas('shipments', function($q) use ($request) { $query->whereHas('shipments', function($q) use ($request) {
$q->where('status', $request->shipment); $q->where('status', $request->shipment);
}); });
} }
// optional ordering
$query->latest('id');
return $query;
}
public function downloadPdf(Request $request)
{
// Build same filtered query used for table
$query = $this->buildOrdersQueryFromRequest($request);
$orders = $query->get(); $orders = $query->get();
$pdf = PDF::loadView('admin.orders.pdf', compact('orders')); // optional: pass filters to view for header
return $pdf->download('orders-report-' . date('Y-m-d') . '.pdf'); $filters = [
} 'search' => $request->search ?? null,
'status' => $request->status ?? null,
'shipment' => $request->shipment ?? null,
];
public function downloadExcel(Request $request) $pdf = PDF::loadView('admin.orders.pdf', compact('orders', 'filters'))
{ ->setPaper('a4', 'landscape'); // adjust if needed
$fileName = 'orders-report'
. ($filters['status'] ? "-{$filters['status']}" : '')
. '-' . date('Y-m-d') . '.pdf';
return $pdf->download($fileName);
}
public function downloadExcel(Request $request)
{
// pass request to OrdersExport which will build Filtered query internally
return Excel::download(new OrdersExport($request), 'orders-report-' . date('Y-m-d') . '.xlsx'); return Excel::download(new OrdersExport($request), 'orders-report-' . date('Y-m-d') . '.xlsx');
} }
//====================================================
// add Temp Item
//=================================================
public function addTempItem(Request $request) public function addTempItem(Request $request)
{ {
// Validate item fields // Validate item fields
$item = $request->validate([ $item = $request->validate([
@@ -484,9 +500,13 @@ class AdminOrderController extends Controller
session()->push('temp_order_items', $item); session()->push('temp_order_items', $item);
return redirect()->to(route('admin.orders.index') . '#createOrderForm') return redirect()->to(route('admin.orders.index') . '#createOrderForm')
->with('success', 'Item added.'); ->with('success', 'Item added.');
} }
// -------------------------------------------------------------------------
// STEP 3 : FINISH ORDER
// -------------------------------------------------------------------------
public function finishOrder(Request $request) public function finishOrder(Request $request)
{ {
@@ -644,5 +664,29 @@ class AdminOrderController extends Controller
return redirect()->route('admin.orders.index') return redirect()->route('admin.orders.index')
->with('success', 'Order + Invoice created successfully.'); ->with('success', 'Order + Invoice created successfully.');
} }
// ---------------------------
// ORDER CRUD: update / destroy
// ---------------------------
public function updateItem(Request $request, $id)
{
$item = OrderItem::findOrFail($id);
$item->update([
'description' => $request->description,
'ctn' => $request->ctn,
'qty' => $request->qty,
'ttl_qty' => $request->ttl_qty,
'unit' => $request->unit,
'price' => $request->price,
'ttl_amount' => $request->ttl_amount,
'cbm' => $request->cbm,
'ttl_cbm' => $request->ttl_cbm,
'kg' => $request->kg,
'ttl_kg' => $request->ttl_kg,
'shop_no' => $request->shop_no,
]);
return back()->with('success', 'Item updated successfully!');
}
} }

View File

@@ -65,4 +65,52 @@ class UserRequestController extends Controller
return redirect()->back()->with('info', 'Request rejected successfully.'); return redirect()->back()->with('info', 'Request rejected successfully.');
} }
public function profileUpdateRequests()
{
$requests = \App\Models\UpdateRequest::where('status', 'pending')
->orderBy('id', 'desc')
->get();
return view('admin.profile_update_requests', compact('requests'));
}
public function approveProfileUpdate($id)
{
$req = \App\Models\UpdateRequest::findOrFail($id);
$user = \App\Models\User::findOrFail($req->user_id);
// FIX: Ensure data is array
$newData = is_array($req->data) ? $req->data : json_decode($req->data, true);
foreach ($newData as $key => $value) {
if ($value !== null && $value !== "") {
if (in_array($key, ['customer_name','company_name','designation','email','mobile_no','address','pincode'])) {
$user->$key = $value;
}
}
}
$user->save();
$req->status = 'approved';
$req->admin_note = 'Approved by admin on ' . now();
$req->save();
return back()->with('success', 'Profile updated successfully.');
}
public function rejectProfileUpdate($id)
{
$req = \App\Models\UpdateRequest::findOrFail($id);
$req->status = 'rejected';
$req->admin_note = 'Rejected by admin on ' . now();
$req->save();
return back()->with('info', 'Profile update request rejected.');
}
} }

View File

@@ -12,19 +12,68 @@ class UserAuthController extends Controller
public function refreshToken() public function refreshToken()
{ {
\Log::info('🔄 refreshToken() called');
try { try {
$newToken = JWTAuth::refresh(JWTAuth::getToken()); // Get current token
$currentToken = JWTAuth::getToken();
if (!$currentToken) {
\Log::warning('⚠ No token provided in refreshToken()');
return response()->json([
'success' => false,
'message' => 'Token not provided',
], 401);
}
\Log::info('📥 Current Token:', ['token' => (string) $currentToken]);
// Try refreshing token
$newToken = JWTAuth::refresh($currentToken);
\Log::info('✅ Token refreshed successfully', ['new_token' => $newToken]);
return response()->json([ return response()->json([
'success' => true, 'success' => true,
'token' => $newToken, 'token' => $newToken,
]); ]);
} catch (\Exception $e) { } catch (\Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
\Log::error('❌ TokenExpiredException in refreshToken()', [
'message' => $e->getMessage(),
]);
return response()->json([
'success' => false,
'message' => 'Token expired, cannot refresh.',
], 401);
} catch (\Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
\Log::error('❌ TokenInvalidException in refreshToken()', [
'message' => $e->getMessage(),
]);
return response()->json([
'success' => false,
'message' => 'Invalid token.',
], 401);
} catch (\Tymon\JWTAuth\Exceptions\JWTException $e) {
\Log::error('❌ JWTException in refreshToken()', [
'message' => $e->getMessage(),
]);
return response()->json([ return response()->json([
'success' => false, 'success' => false,
'message' => 'Could not refresh token.', 'message' => 'Could not refresh token.',
], 401); ], 401);
} catch (\Exception $e) {
\Log::error('❌ General Exception in refreshToken()', [
'message' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
return response()->json([
'success' => false,
'message' => 'Unexpected error while refreshing token.',
], 500);
} }
} }

View File

@@ -4,13 +4,16 @@ namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Models\UpdateRequest;
use PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth; use PHPOpenSourceSaver\JWTAuth\Facades\JWTAuth;
class UserProfileController extends Controller class UserProfileController extends Controller
{ {
/**
* Get user profile
*/
public function profile() public function profile()
{ {
// Get logged-in user using JWT
try { try {
$user = JWTAuth::parseToken()->authenticate(); $user = JWTAuth::parseToken()->authenticate();
} catch (\Exception $e) { } catch (\Exception $e) {
@@ -20,7 +23,6 @@ class UserProfileController extends Controller
], 401); ], 401);
} }
if (! $user) { if (! $user) {
return response()->json([ return response()->json([
'success' => false, 'success' => false,
@@ -28,7 +30,6 @@ class UserProfileController extends Controller
], 401); ], 401);
} }
// Format response
return response()->json([ return response()->json([
'success' => true, 'success' => true,
'data' => [ 'data' => [
@@ -49,8 +50,13 @@ class UserProfileController extends Controller
]); ]);
} }
public function updateProfile(Request $request)
{
/**
* Update profile IMAGE only (no admin approval)
*/
public function updateProfileImage(Request $request)
{
$user = JWTAuth::parseToken()->authenticate(); $user = JWTAuth::parseToken()->authenticate();
if (! $user) { if (! $user) {
@@ -60,34 +66,22 @@ class UserProfileController extends Controller
], 401); ], 401);
} }
// Validate ONLY profile image
$request->validate([ $request->validate([
'profile_image' => 'required|image|mimes:jpg,jpeg,png|max:2048' 'profile_image' => 'required|image|mimes:jpg,jpeg,png|max:2048'
]); ]);
// If new image uploaded
if ($request->hasFile('profile_image')) {
// DELETE OLD IMAGE // DELETE OLD IMAGE
if ($user->profile_image && file_exists(public_path($user->profile_image))) { if ($user->profile_image && file_exists(public_path($user->profile_image))) {
@unlink(public_path($user->profile_image)); @unlink(public_path($user->profile_image));
} }
// NEW FILE // SAVE NEW IMAGE
$file = $request->file('profile_image'); $file = $request->file('profile_image');
$filename = 'profile_' . time() . '.' . $file->getClientOriginalExtension(); $filename = 'profile_' . time() . '.' . $file->getClientOriginalExtension();
// Correct folder name (from your message)
$folder = 'profile_upload/'; $folder = 'profile_upload/';
$fullPath = $folder . $filename;
// Move file
$file->move(public_path($folder), $filename); $file->move(public_path($folder), $filename);
// Save in DB (same pattern you said) $user->profile_image = $folder . $filename;
$user->profile_image = $fullPath;
}
$user->save(); $user->save();
return response()->json([ return response()->json([
@@ -104,9 +98,51 @@ class UserProfileController extends Controller
'pincode' => $user->pincode, 'pincode' => $user->pincode,
'status' => $user->status, 'status' => $user->status,
'customer_type' => $user->customer_type, 'customer_type' => $user->customer_type,
'profile_image' => $user->profile_image ? url($user->profile_image) : null, 'profile_image' => url($user->profile_image),
'date' => $user->date, 'date' => $user->date,
] ]
]);
}
/**
* Submit profile update request (requires admin approval)
*/
public function updateProfileRequest(Request $request)
{
$user = JWTAuth::parseToken()->authenticate();
if (! $user) {
return response()->json([
'success' => false,
'message' => 'Unauthorized'
], 401);
}
// Validate input
$request->validate([
'customer_name' => 'nullable|string|max:255',
'company_name' => 'nullable|string|max:255',
'designation' => 'nullable|string|max:255',
'email' => 'nullable|email',
'mobile_no' => 'nullable|string|max:15',
'address' => 'nullable|string',
'pincode' => 'nullable|string|max:10'
]);
// SAVE AS ARRAY (NOT JSON STRING!)
$updateReq = \App\Models\UpdateRequest::create([
'user_id' => $user->id,
'data' => $request->all(), // <---- FIXED
'status' => 'pending',
]);
return response()->json([
'success' => true,
'message' => 'Profile update request submitted. Waiting for admin approval.',
'request_id' => $updateReq->id
]); ]);
} }

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class UpdateRequest extends Model
{
use HasFactory;
protected $table = 'update_requests';
protected $fillable = [
'user_id',
'data',
'status',
'admin_note',
];
protected $casts = [
'data' => 'array', // converts JSON to array automatically
];
// Relationship: request belongs to a user
public function user()
{
return $this->belongsTo(User::class);
}
}

View File

@@ -10,7 +10,7 @@
"barryvdh/laravel-dompdf": "^3.1", "barryvdh/laravel-dompdf": "^3.1",
"laravel/framework": "^12.0", "laravel/framework": "^12.0",
"laravel/tinker": "^2.10.1", "laravel/tinker": "^2.10.1",
"maatwebsite/excel": "^1.1", "maatwebsite/excel": "^3.1",
"mpdf/mpdf": "^8.2", "mpdf/mpdf": "^8.2",
"php-open-source-saver/jwt-auth": "2.8" "php-open-source-saver/jwt-auth": "2.8"
}, },

1249
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUpdateRequestsTable extends Migration
{
public function up()
{
Schema::create('update_requests', function (Blueprint $table) {
$table->id();
// The user who is requesting profile update
$table->unsignedBigInteger('user_id');
// JSON data of the requested profile changes
$table->json('data')->nullable();
// pending / approved / rejected
$table->enum('status', ['pending', 'approved', 'rejected'])->default('pending');
// Optional message (admin notes)
$table->text('admin_note')->nullable();
$table->timestamps();
// Foreign key constraint
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
public function down()
{
Schema::dropIfExists('update_requests');
}
}

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

View File

@@ -1723,4 +1723,16 @@ document.addEventListener('DOMContentLoaded', function() {
}); });
</script> </script>
<script>
document.addEventListener("hidden.bs.modal", function () {
// Remove Bootstrap backdrops
document.querySelectorAll(".modal-backdrop").forEach(el => el.remove());
// Fix page scroll locking
document.body.classList.remove("modal-open");
document.body.style.overflow = "";
});
</script>
@endsection @endsection

View File

@@ -212,6 +212,13 @@
<i class="bi bi-bag"></i> Orders <i class="bi bi-bag"></i> Orders
</a> </a>
<a href="{{ route('admin.requests') }}" class="{{ request()->routeIs('admin.requests') ? 'active' : '' }}"><i class="bi bi-envelope"></i> Requests</a> <a href="{{ route('admin.requests') }}" class="{{ request()->routeIs('admin.requests') ? 'active' : '' }}"><i class="bi bi-envelope"></i> Requests</a>
<li>
<a href="{{ route('admin.profile.requests') }}">
<i class="bi bi-person-lines-fill"></i>
Profile Update Requests
</a>
</li>
<a href="{{ route('admin.staff') }}" class="{{ request()->routeIs('admin.staff') ? 'active' : '' }}"><i class="bi bi-person-badge"></i> Staff</a> <a href="{{ route('admin.staff') }}" class="{{ request()->routeIs('admin.staff') ? 'active' : '' }}"><i class="bi bi-person-badge"></i> Staff</a>
<a href="{{ route('admin.account') }}" class="{{ request()->routeIs('admin.account') ? 'active' : '' }}"><i class="bi bi-gear"></i> Account</a> <a href="{{ route('admin.account') }}" class="{{ request()->routeIs('admin.account') ? 'active' : '' }}"><i class="bi bi-gear"></i> Account</a>
<a href="{{ route('admin.marklist.index') }}" class="{{ request()->routeIs('admin.marklist.index') ? 'active' : '' }}"><i class="bi bi-list-check"></i> Mark List</a> <a href="{{ route('admin.marklist.index') }}" class="{{ request()->routeIs('admin.marklist.index') ? 'active' : '' }}"><i class="bi bi-list-check"></i> Mark List</a>

View File

@@ -0,0 +1,70 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Orders Report</title>
<style>
body { font-family: DejaVu Sans, sans-serif; font-size:12px; }
table { width:100%; border-collapse: collapse; }
th, td { border: 1px solid #ddd; padding: 6px; text-align: left; }
th { background: #f2f2f2; }
</style>
</head>
<body>
<h3>Orders Report</h3>
@if(!empty($filters))
<p>
@if($filters['search']) Search: <strong>{{ $filters['search'] }}</strong> @endif
@if($filters['status']) &nbsp; | Status: <strong>{{ ucfirst($filters['status']) }}</strong> @endif
@if($filters['shipment']) &nbsp; | Shipment: <strong>{{ ucfirst($filters['shipment']) }}</strong> @endif
</p>
@endif
<table>
<thead>
<tr>
<th>Order ID</th>
<th>Shipment ID</th>
<th>Customer ID</th>
<th>Company</th>
<th>Origin</th>
<th>Destination</th>
<th>Order Date</th>
<th>Invoice No</th>
<th>Invoice Date</th>
<th>Amount</th>
<th>Amount + GST</th>
<th>Invoice Status</th>
<th>Shipment Status</th>
</tr>
</thead>
<tbody>
@forelse($orders as $order)
@php
$mark = $order->markList ?? null;
$invoice = $order->invoice ?? null;
$shipment = $order->shipments->first() ?? null;
@endphp
<tr>
<td>{{ $order->order_id }}</td>
<td>{{ $shipment->shipment_id ?? '-' }}</td>
<td>{{ $mark->customer_id ?? '-' }}</td>
<td>{{ $mark->company_name ?? '-' }}</td>
<td>{{ $mark->origin ?? $order->origin ?? '-' }}</td>
<td>{{ $mark->destination ?? $order->destination ?? '-' }}</td>
<td>{{ $order->created_at ? $order->created_at->format('d-m-Y') : '-' }}</td>
<td>{{ $invoice->invoice_number ?? '-' }}</td>
<td>{{ $invoice?->invoice_date ? \Carbon\Carbon::parse($invoice->invoice_date)->format('d-m-Y') : '-' }}</td>
<td>{{ $invoice?->final_amount ? number_format($invoice->final_amount, 2) : '-' }}</td>
<td>{{ $invoice?->final_amount_with_gst ? number_format($invoice->final_amount_with_gst, 2) : '-' }}</td>
<td>{{ $invoice->status ? ucfirst($invoice->status) : 'Pending' }}</td>
<td>{{ $shipment?->status ? ucfirst(str_replace('_',' ',$shipment->status)) : 'Pending' }}</td>
</tr>
@empty
<tr><td colspan="13" style="text-align:center">No orders found</td></tr>
@endforelse
</tbody>
</table>
</body>
</html>

View File

@@ -0,0 +1,111 @@
@extends('admin.layouts.app')
@section('page-title', 'Profile Update Requests')
@section('content')
<div class="container-fluid px-0">
@php
$perPage = 5;
$currentPage = request()->get('page', 1);
$currentPage = max(1, (int)$currentPage);
$total = $requests->count();
$totalPages = ceil($total / $perPage);
$currentItems = $requests->slice(($currentPage - 1) * $perPage, $perPage);
@endphp
<style>
.old-value { color: #6b7280; font-weight: 600; }
.new-value { color: #111827; font-weight: 700; }
.changed { background: #fef3c7; padding: 6px; border-radius: 6px; }
.box { padding: 10px 14px; border-radius: 8px; background: #f8fafc; margin-bottom: 10px; }
.diff-label { font-size: 13px; font-weight: 700; }
.actions { display: flex; gap: 10px; }
</style>
<h4 class="fw-bold my-3">Profile Update Requests ({{ $total }})</h4>
<div class="card mb-4 shadow-sm">
<div class="card-body pb-1">
<div class="table-responsive custom-table-wrapper">
<table class="table align-middle mb-0 custom-table">
<thead>
<tr>
<th>#</th>
<th>User</th>
<th>Requested Changes</th>
<th>Status</th>
<th>Requested At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@foreach($currentItems as $index => $req)
@php
$user = $req->user;
// FIX: Convert string to array
$newData = is_array($req->data) ? $req->data : json_decode($req->data, true);
@endphp
<tr>
<td><strong>{{ ($currentPage - 1) * $perPage + $index + 1 }}</strong></td>
<td>
<strong>{{ $user->customer_name }}</strong><br>
<small>{{ $user->email }}</small><br>
<small>ID: {{ $user->customer_id }}</small>
</td>
<td>
@foreach($newData as $key => $newValue)
@php
$oldValue = $user->$key ?? '—';
$changed = $oldValue != $newValue;
@endphp
<div class="box {{ $changed ? 'changed' : '' }}">
<span class="diff-label">{{ ucfirst(str_replace('_',' ', $key)) }}:</span><br>
<span class="old-value">Old: {{ $oldValue }}</span><br>
<span class="new-value">New: {{ $newValue ?? '—' }}</span>
</div>
@endforeach
</td>
<td>
@if($req->status == 'pending')
<span class="badge badge-pending">Pending</span>
@elseif($req->status == 'approved')
<span class="badge badge-approved">Approved</span>
@else
<span class="badge badge-rejected">Rejected</span>
@endif
</td>
<td>{{ $req->created_at->format('d M Y, h:i A') }}</td>
<td class="actions">
@if($req->status == 'pending')
<a href="{{ route('admin.profile.approve', $req->id) }}" class="btn btn-success btn-sm">
<i class="bi bi-check-circle"></i> Approve
</a>
<a href="{{ route('admin.profile.reject', $req->id) }}" class="btn btn-danger btn-sm">
<i class="bi bi-x-circle"></i> Reject
</a>
@else
<span class="text-muted">Completed</span>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
@endsection

View File

@@ -7,18 +7,15 @@
/*Remove horizontal scroll bar*/ /*Remove horizontal scroll bar*/
html, body { html, body {
overflow-x: hidden !important; overflow-x: hidden !important;
font-family: 'Inter', sans-serif;
} }
.table thead th, .table thead th,
.table tbody td { .table tbody td {
white-space: nowrap !important; white-space: nowrap !important;
padding: 14px 8px !important; padding: 8px 4px !important;
font-size: 14px;
font-family: 'Inter', sans-serif;
} }
.table th:nth-child(10), .table th:nth-child(10), /* if Date is column 10 */
.table td:nth-child(10) { .table td:nth-child(10) {
max-width: 110px !important; max-width: 110px !important;
width: 110px !important; width: 110px !important;
@@ -28,7 +25,6 @@
.table { .table {
table-layout: fixed !important; table-layout: fixed !important;
font-family: 'Inter', sans-serif;
} }
@@ -36,7 +32,6 @@
min-width: unset !important; min-width: unset !important;
width: 100% !important; width: 100% !important;
table-layout: auto !important; table-layout: auto !important;
font-family: 'Inter', sans-serif;
} }
.table thead th, .table thead th,
@@ -47,8 +42,6 @@
.shipment-details-table td { .shipment-details-table td {
white-space: normal !important; white-space: normal !important;
word-break: break-word; word-break: break-word;
font-family: 'Inter', sans-serif;
font-size: 14px;
} }
.table-responsive, .modal .table-responsive { .table-responsive, .modal .table-responsive {
@@ -76,27 +69,25 @@
align-items: center; align-items: center;
gap: 15px; gap: 15px;
padding: 20px; padding: 20px;
background: white; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 16px; border-radius: 16px;
box-shadow: var(--card-shadow); box-shadow: var(--card-shadow);
flex-wrap: wrap; flex-wrap: wrap;
margin-bottom: 30px; margin-bottom: 30px;
color: #333; color: white;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
font-family: 'Inter', sans-serif;
border: 1px solid #e2e8f0;
} }
.search-input-container { .search-shipment-bar::before {
display: flex; content: '';
flex: 1; position: absolute;
min-width: 300px; top: 0;
background: white; left: 0;
border-radius: 10px; right: 0;
overflow: hidden; bottom: 0;
border: 1px solid #d1d5db; background: rgba(255,255,255,0.1);
transition: all 0.3s ease; z-index: 0;
} }
.search-input-container:focus-within { .search-input-container:focus-within {
@@ -164,31 +155,31 @@
color: white; color: white;
} }
.search-shipment-bar input,
.search-shipment-bar select { .search-shipment-bar select {
padding: 20px 16px; padding: 12px 16px;
border: 1px solid #d1d5db; border: 1px solid rgba(255,255,255,0.2);
border-radius: 10px; border-radius: 10px;
flex: 1;
min-width: 150px; min-width: 150px;
background: white; background: rgba(255,255,255,0.9);
font-weight: 500; font-weight: 500;
transition: all 0.3s ease; transition: all 0.3s ease;
font-family: 'Inter', sans-serif;
font-size: 14px;
color: #333;
} }
.search-shipment-bar input:focus,
.search-shipment-bar select:focus { .search-shipment-bar select:focus {
background: white; background: white;
box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.1); box-shadow: 0 0 0 3px rgba(255,255,255,0.3);
outline: none; outline: none;
border-color: #4361ee;
} }
.btn-add-shipment { .btn-add-shipment {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background: rgba(255,255,255,0.2);
backdrop-filter: blur(10px);
color: white; color: white;
border: none; border: 1px solid rgba(255,255,255,0.3);
padding: 17px 24px; padding: 12px 24px;
border-radius: 10px; border-radius: 10px;
cursor: pointer; cursor: pointer;
display: flex; display: flex;
@@ -197,13 +188,17 @@
transition: all 0.3s ease; transition: all 0.3s ease;
white-space: nowrap; white-space: nowrap;
font-weight: 600; font-weight: 600;
font-family: 'Inter', sans-serif;
font-size: 14px;
} }
.btn-add-shipment:hover { .btn-add-shipment:hover {
background: rgba(255,255,255,0.3);
transform: translateY(-2px); transform: translateY(-2px);
box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3); 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));
} }
.truck-icon { .truck-icon {
@@ -215,7 +210,7 @@
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
} }
.search-input-container, .search-shipment-bar input,
.search-shipment-bar select { .search-shipment-bar select {
width: 100%; width: 100%;
} }
@@ -248,7 +243,6 @@
box-shadow: var(--card-shadow); box-shadow: var(--card-shadow);
transition: all 0.3s ease; transition: all 0.3s ease;
overflow: hidden; overflow: hidden;
font-family: 'Inter', sans-serif;
} }
.card:hover { .card:hover {
@@ -262,7 +256,6 @@
border: none; border: none;
padding: 20px 25px; padding: 20px 25px;
border-radius: 16px 16px 0 0 !important; border-radius: 16px 16px 0 0 !important;
font-family: 'Inter', sans-serif;
} }
.card-header h5 { .card-header h5 {
@@ -271,8 +264,6 @@
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
font-family: 'Inter', sans-serif;
font-size: 18px;
} }
/* Table Styles */ /* Table Styles */
@@ -288,7 +279,6 @@
width: 100%; width: 100%;
min-width: 1200px; min-width: 1200px;
padding: 0; padding: 0;
font-family: 'Inter', sans-serif;
} }
.table thead th { .table thead th {
@@ -302,8 +292,6 @@
border-bottom: 2px solid var(--border); border-bottom: 2px solid var(--border);
position: relative; position: relative;
white-space: nowrap; white-space: nowrap;
font-family: 'Inter', sans-serif;
font-size: 14px;
} }
.table thead th:first-child { .table thead th:first-child {
@@ -332,8 +320,6 @@
border-bottom: 1px solid var(--border); border-bottom: 1px solid var(--border);
font-weight: 500; font-weight: 500;
white-space: nowrap; white-space: nowrap;
font-family: 'Inter', sans-serif;
font-size: 14px;
} }
.table tbody tr:last-child td { .table tbody tr:last-child td {
@@ -349,13 +335,8 @@
border: 2px solid transparent !important; border: 2px solid transparent !important;
min-width: 40px !important; min-width: 40px !important;
text-align: center !important; text-align: center !important;
display: inline-flex !important; display: inline-block !important;
align-items: center;
justify-content: center;
line-height: 1.2 !important; line-height: 1.2 !important;
font-family: 'Inter', sans-serif;
gap: 6px;
width: 110px;
} }
/* Status icons */ /* Status icons */
@@ -371,6 +352,7 @@
background: linear-gradient(135deg, #fef3c7, #fde68a) !important; background: linear-gradient(135deg, #fef3c7, #fde68a) !important;
color: #d97706 !important; color: #d97706 !important;
border-color: #f59e0b !important; border-color: #f59e0b !important;
width: 110px;
} }
/* In Transit Status - SAME SIZE WITH TRUCK ICON */ /* In Transit Status - SAME SIZE WITH TRUCK ICON */
@@ -378,6 +360,7 @@
background: linear-gradient(135deg, #dbeafe, #93c5fd) !important; background: linear-gradient(135deg, #dbeafe, #93c5fd) !important;
color: #1e40af !important; color: #1e40af !important;
border-color: #3b82f6 !important; border-color: #3b82f6 !important;
width: 110px;
} }
/* Dispatched Status - SAME SIZE WITH BOX ICON */ /* Dispatched Status - SAME SIZE WITH BOX ICON */
@@ -385,6 +368,7 @@
background: linear-gradient(135deg, #e9d5ff, #c4b5fd) !important; background: linear-gradient(135deg, #e9d5ff, #c4b5fd) !important;
color: #6b21a8 !important; color: #6b21a8 !important;
border-color: #8b5cf6 !important; border-color: #8b5cf6 !important;
width: 110px;
} }
/* Delivered Status - SAME SIZE WITH CHECK ICON */ /* Delivered Status - SAME SIZE WITH CHECK ICON */
@@ -392,6 +376,7 @@
background: linear-gradient(135deg, #d1fae5, #a7f3d0) !important; background: linear-gradient(135deg, #d1fae5, #a7f3d0) !important;
color: #065f46 !important; color: #065f46 !important;
border-color: #10b981 !important; border-color: #10b981 !important;
width: 110px;
} }
/* Default badge styles - SAME SIZE */ /* Default badge styles - SAME SIZE */
@@ -422,9 +407,6 @@
border: 1px solid #dee2e6 !important; border: 1px solid #dee2e6 !important;
min-width: 80px !important; min-width: 80px !important;
padding: 6px 12px !important; padding: 6px 12px !important;
font-family: 'Inter', sans-serif;
font-size: 13px;
width: auto;
} }
/* NEW: Action Button Styles */ /* NEW: Action Button Styles */
@@ -446,7 +428,6 @@
justify-content: center; justify-content: center;
width: 36px; width: 36px;
height: 36px; height: 36px;
font-family: 'Inter', sans-serif;
} }
.btn-edit-status:hover { .btn-edit-status:hover {
@@ -470,7 +451,6 @@
margin-top: -50px; margin-top: -50px;
border: 1px solid var(--border); border: 1px solid var(--border);
z-index: 1050; z-index: 1050;
font-family: 'Inter', sans-serif;
} }
.status-dropdown.show { .status-dropdown.show {
@@ -491,7 +471,6 @@
gap: 8px; gap: 8px;
background: transparent; background: transparent;
width: 100%; width: 100%;
font-family: 'Inter', sans-serif;
} }
.status-option:hover { .status-option:hover {
@@ -623,7 +602,6 @@
border: none; border: none;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
overflow: hidden; overflow: hidden;
font-family: 'Inter', sans-serif;
} }
.modal-header { .modal-header {
@@ -633,7 +611,6 @@
padding: 25px 30px 15px; padding: 25px 30px 15px;
border-radius: 20px 20px 0 0; border-radius: 20px 20px 0 0;
position: relative; position: relative;
font-family: 'Inter', sans-serif;
} }
.modal-header::after { .modal-header::after {
@@ -649,7 +626,6 @@
.modal-title { .modal-title {
font-weight: 700; font-weight: 700;
font-size: 1.5rem; font-size: 1.5rem;
font-family: 'Inter', sans-serif;
} }
.btn-close { .btn-close {
@@ -663,7 +639,6 @@
.modal-body { .modal-body {
padding: 25px 30px; padding: 25px 30px;
font-family: 'Inter', sans-serif;
} }
/* Form Styles */ /* Form Styles */
@@ -672,18 +647,16 @@
color: #5a6c7d; color: #5a6c7d;
margin-bottom: 8px; margin-bottom: 8px;
font-size: 0.9rem; font-size: 0.9rem;
font-family: 'Inter', sans-serif;
} }
.form-control { .form-control {
border-radius: 10px; border-radius: 10px;
border: 1px solid #e2e8f0; border: 1px solid #e2e8f0;
padding: 12px 16px; padding: 12px 16px;
font-size: 14px; font-size: 15px;
transition: all 0.3s ease; transition: all 0.3s ease;
background: #fafbfc; background: #fafbfc;
color: #4a5568; color: #4a5568;
font-family: 'Inter', sans-serif;
} }
.form-control:focus { .form-control:focus {
@@ -738,8 +711,6 @@
font-weight: 600; font-weight: 600;
padding: 12px 30px; padding: 12px 30px;
transition: all 0.3s ease; transition: all 0.3s ease;
font-family: 'Inter', sans-serif;
font-size: 14px;
} }
.btn-cancel:hover { .btn-cancel:hover {
@@ -753,12 +724,11 @@
background: linear-gradient(135deg, #48bb78, #38a169); background: linear-gradient(135deg, #48bb78, #38a169);
color: white; color: white;
font-weight: 600; font-weight: 600;
font-size: 14px; font-size: 16px;
border-radius: 10px; border-radius: 10px;
padding: 12px 35px; padding: 12px 35px;
border: none; border: none;
transition: all 0.3s ease; transition: all 0.3s ease;
font-family: 'Inter', sans-serif;
} }
.btn-create:hover { .btn-create:hover {
@@ -774,7 +744,6 @@
border-spacing: 0 8px; border-spacing: 0 8px;
margin: 0; margin: 0;
min-width: 1300px; min-width: 1300px;
font-family: 'Inter', sans-serif;
} }
.custom-table-modal thead th { .custom-table-modal thead th {
@@ -785,10 +754,9 @@
border: 1px solid #e2e8f0; border: 1px solid #e2e8f0;
text-align: center; text-align: center;
position: relative; position: relative;
font-size: 14px; font-size: 0.9rem;
letter-spacing: 0.3px; letter-spacing: 0.3px;
white-space: nowrap; white-space: nowrap;
font-family: 'Inter', sans-serif;
} }
.custom-table-modal thead th:first-child { .custom-table-modal thead th:first-child {
@@ -825,8 +793,6 @@
position: relative; position: relative;
color: #4a5568; color: #4a5568;
white-space: nowrap; white-space: nowrap;
font-family: 'Inter', sans-serif;
font-size: 14px;
} }
.custom-table-modal tbody tr td:first-child { .custom-table-modal tbody tr td:first-child {
@@ -881,12 +847,10 @@
border: none; border: none;
padding: 25px 30px 15px; padding: 25px 30px 15px;
border-radius: 20px 20px 0 0; border-radius: 20px 20px 0 0;
font-family: 'Inter', sans-serif;
} }
.shipment-details-body { .shipment-details-body {
padding: 40px 45px; padding: 40px 45px;
font-family: 'Inter', sans-serif;
} }
.shipment-info-row { .shipment-info-row {
@@ -897,7 +861,6 @@
background: #f8fafc; background: #f8fafc;
border-radius: 12px; border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05); box-shadow: 0 2px 10px rgba(0,0,0,0.05);
font-family: 'Inter', sans-serif;
} }
.shipment-info-item { .shipment-info-item {
@@ -911,14 +874,12 @@
color: #64748b; color: #64748b;
font-size: 14px; font-size: 14px;
margin-bottom: 5px; margin-bottom: 5px;
font-family: 'Inter', sans-serif;
} }
.shipment-info-value { .shipment-info-value {
font-weight: 700; font-weight: 700;
font-size: 18px; font-size: 18px;
color: var(--dark); color: var(--dark);
font-family: 'Inter', sans-serif;
} }
.shipment-details-table { .shipment-details-table {
@@ -927,7 +888,6 @@
border-spacing: 0 8px; border-spacing: 0 8px;
margin-top: 20px; margin-top: 20px;
min-width: 1400px; min-width: 1400px;
font-family: 'Inter', sans-serif;
} }
.shipment-details-table th { .shipment-details-table th {
@@ -939,8 +899,6 @@
border: none; border: none;
position: relative; position: relative;
white-space: nowrap; white-space: nowrap;
font-family: 'Inter', sans-serif;
font-size: 14px;
} }
.shipment-details-table th:first-child { .shipment-details-table th:first-child {
@@ -960,8 +918,6 @@
background: white; background: white;
box-shadow: 0 2px 5px rgba(0,0,0,0.05); box-shadow: 0 2px 5px rgba(0,0,0,0.05);
white-space: nowrap; white-space: nowrap;
font-family: 'Inter', sans-serif;
font-size: 14px;
} }
.shipment-details-table tr td:first-child { .shipment-details-table tr td:first-child {
@@ -982,7 +938,6 @@
border-radius: 12px; border-radius: 12px;
box-shadow: 0 4px 6px rgba(0,0,0,0.05); box-shadow: 0 4px 6px rgba(0,0,0,0.05);
border-left: 4px solid #4361ee; border-left: 4px solid #4361ee;
font-family: 'Inter', sans-serif;
} }
.shipment-totals-row { .shipment-totals-row {
@@ -1009,7 +964,6 @@
margin-bottom: 8px; margin-bottom: 8px;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.5px; letter-spacing: 0.5px;
font-family: 'Inter', sans-serif;
} }
.shipment-total-value { .shipment-total-value {
@@ -1017,7 +971,6 @@
font-size: 20px; font-size: 20px;
color: #1e293b; color: #1e293b;
line-height: 1.2; line-height: 1.2;
font-family: 'Inter', sans-serif;
} }
.total-amount { .total-amount {
@@ -1090,7 +1043,6 @@
/* Status Filter Styles */ /* Status Filter Styles */
.status-filter-container { .status-filter-container {
position: relative; position: relative;
margin-left:350px;
} }
.status-filter-select { .status-filter-select {
@@ -1126,14 +1078,12 @@
margin-top: 15px; margin-top: 15px;
padding: 12px 25px; padding: 12px 25px;
border-top: 1px solid #eef3fb; border-top: 1px solid #eef3fb;
font-family: 'Inter', sans-serif;
} }
.pagination-info { .pagination-info {
font-size: 13px; font-size: 13px;
color: #9ba5bb; color: #9ba5bb;
font-weight: 600; font-weight: 600;
font-family: 'Inter', sans-serif;
} }
.pagination-controls { .pagination-controls {
@@ -1157,7 +1107,6 @@
justify-content: center; justify-content: center;
min-width: 40px; min-width: 40px;
height: 32px; height: 32px;
font-family: 'Inter', sans-serif;
} }
.pagination-btn:hover:not(:disabled) { .pagination-btn:hover:not(:disabled) {
@@ -1186,7 +1135,6 @@
transition: all 0.3s ease; transition: all 0.3s ease;
min-width: 36px; min-width: 36px;
text-align: center; text-align: center;
font-family: 'Inter', sans-serif;
} }
.pagination-page-btn:hover { .pagination-page-btn:hover {
@@ -1211,7 +1159,6 @@
color: #9ba5bb; color: #9ba5bb;
font-size: 13px; font-size: 13px;
padding: 0 4px; padding: 0 4px;
font-family: 'Inter', sans-serif;
} }
/* Image-based pagination buttons */ /* Image-based pagination buttons */
@@ -1540,7 +1487,7 @@
</tr> </tr>
@empty @empty
<tr> <tr>
<td colspan="12" class="text-center py-5 text-muted"> <td colspan="11" class="text-center py-5 text-muted">
<i class="bi bi-inbox display-4 d-block mb-3"></i> <i class="bi bi-inbox display-4 d-block mb-3"></i>
No shipments found No shipments found
</td> </td>
@@ -1754,7 +1701,7 @@ function renderTable() {
if (filteredShipments.length === 0) { if (filteredShipments.length === 0) {
tbody.innerHTML = ` tbody.innerHTML = `
<tr> <tr>
<td colspan="12" class="text-center py-5 text-muted"> <td colspan="11" class="text-center py-5 text-muted">
<i class="bi bi-search display-4 d-block mb-3"></i> <i class="bi bi-search display-4 d-block mb-3"></i>
No shipments found matching your criteria No shipments found matching your criteria
</td> </td>
@@ -1789,9 +1736,9 @@ function renderTable() {
</td> </td>
<td>${shipment.origin}</td> <td>${shipment.origin}</td>
<td>${shipment.destination}</td> <td>${shipment.destination}</td>
<td>${shipment.total_qty}</td> <td><span class="badge bg-light text-dark">${shipment.total_qty}</span></td>
<td>${shipment.total_kg} kg</td> <td><span class="badge bg-light text-dark">${shipment.total_kg} kg</span></td>
<td>${shipment.total_cbm} CBM</td> <td><span class="badge bg-light text-dark">${shipment.total_cbm} CBM</span></td>
<td class="fw-bold text-success">${parseFloat(shipment.total_amount).toLocaleString('en-IN', {minimumFractionDigits: 2, maximumFractionDigits: 2})}</td> <td class="fw-bold text-success">${parseFloat(shipment.total_amount).toLocaleString('en-IN', {minimumFractionDigits: 2, maximumFractionDigits: 2})}</td>
<td> <td>
<span class="badge badge-${shipment.status}"> <span class="badge badge-${shipment.status}">

View File

@@ -15,7 +15,9 @@ Route::post('/signup-request', [RequestController::class, 'usersignup']);
Route::post('/user/login', [UserAuthController::class, 'login']); Route::post('/user/login', [UserAuthController::class, 'login']);
Route::middleware(['auth:api'])->group(function () { Route::middleware(['auth:api'])->group(function () {
//Route::post('/user/refresh', [UserAuthController::class, 'refreshToken']);
Route::post('/user/logout', [UserAuthController::class, 'logout']); Route::post('/user/logout', [UserAuthController::class, 'logout']);
@@ -37,6 +39,11 @@ Route::middleware(['auth:api'])->group(function () {
Route::get('/user/invoice/{invoice_id}/installments', [UserOrderController::class, 'invoiceInstallmentsById']); Route::get('/user/invoice/{invoice_id}/installments', [UserOrderController::class, 'invoiceInstallmentsById']);
// Profile // Profile
Route::get('/user/profile', [UserProfileController::class, 'profile']); Route::get('/user/profile', [UserProfileController::class, 'profile']);
Route::post('/user/profile/update', [UserProfileController::class, 'updateProfile']); Route::post('/user/profile-image', [UserProfileController::class, 'updateProfileImage']);
Route::post('/user/profile-update-request', [UserProfileController::class, 'updateProfileRequest']);
// Route::post('/user/profile/update', [UserProfileController::class, 'updateProfile']);
}); });

View File

@@ -75,6 +75,20 @@ Route::prefix('admin')
Route::get('/requests/reject/{id}', [UserRequestController::class, 'reject']) Route::get('/requests/reject/{id}', [UserRequestController::class, 'reject'])
->name('admin.requests.reject'); ->name('admin.requests.reject');
// PROFILE UPDATE REQUESTS
Route::get('/profile-update-requests',
[UserRequestController::class, 'profileUpdateRequests']
)->name('admin.profile.requests');
Route::get('/profile-update/approve/{id}',
[UserRequestController::class, 'approveProfileUpdate']
)->name('admin.profile.approve');
Route::get('/profile-update/reject/{id}',
[UserRequestController::class, 'rejectProfileUpdate']
)->name('admin.profile.reject');
// --------------------------- // ---------------------------
// MARK LIST // MARK LIST
@@ -174,6 +188,7 @@ Route::prefix('admin')
Route::post('/shipments/{id}/add-orders', [ShipmentController::class, 'addOrders']) Route::post('/shipments/{id}/add-orders', [ShipmentController::class, 'addOrders'])
->name('admin.shipments.addOrders'); ->name('admin.shipments.addOrders');
// --------------------------- // ---------------------------
// INVOICES // INVOICES
// --------------------------- // ---------------------------
@@ -195,6 +210,8 @@ Route::prefix('admin')
Route::post('/invoices/{id}/installment', [AdminInvoiceController::class, 'storeInstallment']) Route::post('/invoices/{id}/installment', [AdminInvoiceController::class, 'storeInstallment'])
->name('admin.invoice.installment.store'); ->name('admin.invoice.installment.store');
Route::delete('/installment/{id}', [AdminInvoiceController::class, 'deleteInstallment']) Route::delete('/installment/{id}', [AdminInvoiceController::class, 'deleteInstallment'])
->name('admin.invoice.installment.delete'); ->name('admin.invoice.installment.delete');
@@ -278,8 +295,11 @@ Route::prefix('admin')
// --------------------------- // ---------------------------
// REPORTS DOWNLOAD ROUTES // REPORTS DOWNLOAD ROUTES
// --------------------------- // ---------------------------
Route::get('/admin/orders/download/pdf', [OrderController::class, 'downloadPdf'])->name('admin.orders.download.pdf'); Route::get('/admin/orders/download/pdf', [AdminOrderController::class, 'downloadPdf'])
Route::get('/admin/orders/download/excel', [OrderController::class, 'downloadExcel'])->name('admin.orders.download.excel'); ->name('admin.orders.download.pdf');
Route::get('/admin/orders/download/excel', [AdminOrderController::class, 'downloadExcel'])
->name('admin.orders.download.excel');
//--------------------------- //---------------------------
//Edit Button Route //Edit Button Route