customer section
This commit is contained in:
134
app/Http/Controllers/Admin/AdminCustomerController.php
Normal file
134
app/Http/Controllers/Admin/AdminCustomerController.php
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Models\User;
|
||||||
|
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;
|
||||||
|
|
||||||
|
$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'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// SHOW ADD CUSTOMER FORM
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
return view('admin.customers_add');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// STORE NEW CUSTOMER
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'customer_name' => 'required|string|max:255',
|
||||||
|
'company_name' => 'nullable|string|max:255',
|
||||||
|
'designation' => 'nullable|string|max:255',
|
||||||
|
'email' => 'required|email|unique:users,email',
|
||||||
|
'mobile_no' => 'required|string|max:20',
|
||||||
|
'address' => 'nullable|string',
|
||||||
|
'pincode' => 'nullable|string|max:10',
|
||||||
|
'customer_type' => 'required|in:regular,premium',
|
||||||
|
'status' => 'required|in:active,inactive',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// AUTO GENERATE CUSTOMER ID
|
||||||
|
$year = date('Y');
|
||||||
|
$prefix = "CID-$year-";
|
||||||
|
|
||||||
|
$lastCustomer = User::whereYear('created_at', $year)
|
||||||
|
->orderBy('id', 'DESC')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$next = $lastCustomer ? intval(substr($lastCustomer->customer_id, -6)) + 1 : 1;
|
||||||
|
$customerId = $prefix . str_pad($next, 6, '0', STR_PAD_LEFT);
|
||||||
|
|
||||||
|
// CREATE CUSTOMER
|
||||||
|
User::create([
|
||||||
|
'customer_id' => $customerId,
|
||||||
|
'customer_name' => $request->customer_name,
|
||||||
|
'company_name' => $request->company_name,
|
||||||
|
'designation' => $request->designation,
|
||||||
|
'email' => $request->email,
|
||||||
|
'mobile_no' => $request->mobile_no,
|
||||||
|
'address' => $request->address,
|
||||||
|
'pincode' => $request->pincode,
|
||||||
|
'date' => date('Y-m-d'),
|
||||||
|
'customer_type' => $request->customer_type,
|
||||||
|
'status' => $request->status,
|
||||||
|
'password' => Hash::make('123456'), // DEFAULT PASSWORD
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->route('admin.customers.index')
|
||||||
|
->with('success', 'Customer added successfully!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// VIEW CUSTOMER FULL DETAILS
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
public function view($id)
|
||||||
|
{
|
||||||
|
$customer = User::with(['marks', 'orders'])->findOrFail($id);
|
||||||
|
|
||||||
|
$totalOrders = $customer->orders->count();
|
||||||
|
$totalAmount = $customer->orders->sum('ttl_amount');
|
||||||
|
$recentOrders = $customer->orders()->latest()->take(5)->get();
|
||||||
|
|
||||||
|
return view('admin.customers_view', compact(
|
||||||
|
'customer',
|
||||||
|
'totalOrders',
|
||||||
|
'totalAmount',
|
||||||
|
'recentOrders'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// TOGGLE STATUS ACTIVE / INACTIVE
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
public function toggleStatus($id)
|
||||||
|
{
|
||||||
|
$customer = User::findOrFail($id);
|
||||||
|
|
||||||
|
$customer->status = $customer->status === 'active'
|
||||||
|
? 'inactive'
|
||||||
|
: 'active';
|
||||||
|
|
||||||
|
$customer->save();
|
||||||
|
|
||||||
|
return back()->with('success', 'Customer status updated.');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ class User extends Authenticatable implements JWTSubject
|
|||||||
* The attributes that are mass assignable.
|
* The attributes that are mass assignable.
|
||||||
*/
|
*/
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'customer_id', // CID-2025-000001 format
|
'customer_id',
|
||||||
'customer_name',
|
'customer_name',
|
||||||
'company_name',
|
'company_name',
|
||||||
'designation',
|
'designation',
|
||||||
@@ -25,10 +25,15 @@ class User extends Authenticatable implements JWTSubject
|
|||||||
'pincode',
|
'pincode',
|
||||||
'date',
|
'date',
|
||||||
'password',
|
'password',
|
||||||
|
|
||||||
|
// newly added customer fields
|
||||||
|
'status', // active / inactive
|
||||||
|
'customer_type', // premium / regular
|
||||||
|
'profile_image', // optional image
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be hidden for arrays.
|
* Attributes that should be hidden.
|
||||||
*/
|
*/
|
||||||
protected $hidden = [
|
protected $hidden = [
|
||||||
'password',
|
'password',
|
||||||
@@ -36,7 +41,7 @@ class User extends Authenticatable implements JWTSubject
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be cast.
|
* Attribute casting.
|
||||||
*/
|
*/
|
||||||
protected function casts(): array
|
protected function casts(): array
|
||||||
{
|
{
|
||||||
@@ -47,7 +52,30 @@ class User extends Authenticatable implements JWTSubject
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JWT Identifier.
|
* Relationship: User → MarkList (Many)
|
||||||
|
*/
|
||||||
|
public function marks()
|
||||||
|
{
|
||||||
|
return $this->hasMany(\App\Models\MarkList::class, 'customer_id', 'customer_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Relationship: User → Orders (Through MarkList)
|
||||||
|
*/
|
||||||
|
public function orders()
|
||||||
|
{
|
||||||
|
return $this->hasManyThrough(
|
||||||
|
\App\Models\Order::class,
|
||||||
|
\App\Models\MarkList::class,
|
||||||
|
'customer_id', // MarkList.customer_id
|
||||||
|
'mark_no', // Orders.mark_no
|
||||||
|
'customer_id', // Users.customer_id
|
||||||
|
'mark_no' // MarkList.mark_no
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JWT Identifier
|
||||||
*/
|
*/
|
||||||
public function getJWTIdentifier()
|
public function getJWTIdentifier()
|
||||||
{
|
{
|
||||||
@@ -55,7 +83,7 @@ class User extends Authenticatable implements JWTSubject
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JWT Custom Claims.
|
* JWT Custom Claims
|
||||||
*/
|
*/
|
||||||
public function getJWTCustomClaims()
|
public function getJWTCustomClaims()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
|
||||||
|
// status: active / inactive
|
||||||
|
$table->enum('status', ['active', 'inactive'])->default('active')->after('pincode');
|
||||||
|
|
||||||
|
// premium / regular
|
||||||
|
$table->enum('customer_type', ['regular', 'premium'])->default('regular')->after('status');
|
||||||
|
|
||||||
|
// optional: profile image path
|
||||||
|
$table->string('profile_image')->nullable()->after('customer_type');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['status', 'customer_type', 'profile_image']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
BIN
public/invoices/invoice-INV-2025-000001.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000001.pdf
Normal file
Binary file not shown.
BIN
public/invoices/invoice-INV-2025-000004.pdf
Normal file
BIN
public/invoices/invoice-INV-2025-000004.pdf
Normal file
Binary file not shown.
@@ -1,12 +1,176 @@
|
|||||||
@extends('admin.layouts.app')
|
@extends('admin.layouts.app')
|
||||||
|
|
||||||
@section('page-title', 'Dashboard')
|
@section('page-title', 'Customers')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.btn.active {
|
||||||
|
opacity: 1 !important;
|
||||||
|
border-width: 2px;
|
||||||
|
}
|
||||||
|
.btn {
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
.bg-purple {
|
||||||
|
background: #7c3aed !important;
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<div class="card shadow-sm">
|
<div class="card shadow-sm">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h4>Welcome to the Admin customer page</h4>
|
|
||||||
<p>Here you can manage all system modules.</p>
|
<h4 class="mb-3">Customer List</h4>
|
||||||
|
|
||||||
|
{{-- SEARCH + STATUS FILTER ROW --}}
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
|
|
||||||
|
{{-- SEARCH BAR --}}
|
||||||
|
<form method="GET" action="{{ route('admin.customers.index') }}" class="d-flex" style="gap:10px;">
|
||||||
|
|
||||||
|
<input type="text"
|
||||||
|
name="search"
|
||||||
|
value="{{ $search ?? '' }}"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="Search customer name, email, mobile, customer ID...">
|
||||||
|
|
||||||
|
{{-- Preserve status on search --}}
|
||||||
|
@if(!empty($status))
|
||||||
|
<input type="hidden" name="status" value="{{ $status }}">
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<button class="btn btn-primary">
|
||||||
|
<i class="bi bi-search"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{{-- STATUS FILTER --}}
|
||||||
|
<div>
|
||||||
|
<a href="{{ route('admin.customers.index', ['status'=>'active', 'search'=>$search ?? '']) }}"
|
||||||
|
class="btn btn-success {{ ($status ?? '') == 'active' ? 'active' : '' }}">
|
||||||
|
Active
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="{{ route('admin.customers.index', ['status'=>'inactive', 'search'=>$search ?? '']) }}"
|
||||||
|
class="btn btn-danger {{ ($status ?? '') == 'inactive' ? 'active' : '' }}">
|
||||||
|
Inactive
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="{{ route('admin.customers.index') }}"
|
||||||
|
class="btn btn-secondary {{ empty($status) ? 'active' : '' }}">
|
||||||
|
All
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
|
<h4>Customer List</h4>
|
||||||
|
<a href="{{ route('admin.customers.add') }}" class="btn btn-success">
|
||||||
|
<i class="bi bi-plus-circle"></i> Add Customer
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{{-- TABLE --}}
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered align-middle">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>Customer Info</th>
|
||||||
|
<th>Customer ID</th>
|
||||||
|
<th>Create Date</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th width="120">Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
@forelse($customers as $c)
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
{{-- CUSTOMER INFO --}}
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
|
||||||
|
{{-- Avatar --}}
|
||||||
|
<div class="rounded-circle bg-primary text-white d-flex align-items-center justify-content-center me-3"
|
||||||
|
style="width:45px; height:45px; font-size:18px;">
|
||||||
|
{{ strtoupper(substr($c->customer_name,0,1)) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<strong>{{ $c->customer_name }}</strong><br>
|
||||||
|
|
||||||
|
{{-- Customer Type --}}
|
||||||
|
@if($c->customer_type == 'premium')
|
||||||
|
<span class="badge bg-purple">Premium Customer</span>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-secondary">Regular Customer</span>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="text-muted">{{ $c->email }}</div>
|
||||||
|
<div class="text-muted">{{ $c->mobile_no }}</div>
|
||||||
|
|
||||||
|
<div class="text-muted">{{ $c->orders->count() }} orders</div>
|
||||||
|
<div class="text-muted">
|
||||||
|
₹{{ number_format($c->orders->sum('ttl_amount'), 2) }} total
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{{-- CUSTOMER ID --}}
|
||||||
|
<td>{{ $c->customer_id }}</td>
|
||||||
|
|
||||||
|
{{-- CREATED DATE --}}
|
||||||
|
<td>{{ $c->created_at ? $c->created_at->format('d-m-Y') : '-' }}</td>
|
||||||
|
|
||||||
|
{{-- STATUS --}}
|
||||||
|
<td>
|
||||||
|
@if($c->status === 'active')
|
||||||
|
<span class="badge bg-success">Active</span>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-danger">Inactive</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{{-- ACTION BUTTONS --}}
|
||||||
|
<td>
|
||||||
|
|
||||||
|
{{-- VIEW --}}
|
||||||
|
<a href="{{ route('admin.customers.view', $c->id) }}"
|
||||||
|
class="btn btn-sm btn-primary">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{{-- TOGGLE STATUS --}}
|
||||||
|
<form action="{{ route('admin.customers.status', $c->id) }}"
|
||||||
|
method="POST" style="display:inline-block;">
|
||||||
|
@csrf
|
||||||
|
<button class="btn btn-sm btn-warning" title="Toggle Status">
|
||||||
|
<i class="bi bi-power"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="5" class="text-center text-muted">
|
||||||
|
No customers found.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|||||||
95
resources/views/admin/customers_add.blade.php
Normal file
95
resources/views/admin/customers_add.blade.php
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
@extends('admin.layouts.app')
|
||||||
|
|
||||||
|
@section('page-title', 'Add Customer')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<div class="container py-4">
|
||||||
|
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-header bg-light">
|
||||||
|
<strong>Add New Customer</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<form action="{{ route('admin.customers.store') }}" method="POST">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="row g-3">
|
||||||
|
|
||||||
|
{{-- CUSTOMER NAME --}}
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Customer Name *</label>
|
||||||
|
<input type="text" name="customer_name" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- COMPANY NAME --}}
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Company Name</label>
|
||||||
|
<input type="text" name="company_name" class="form-control">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- DESIGNATION --}}
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Designation</label>
|
||||||
|
<input type="text" name="designation" class="form-control">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- EMAIL --}}
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Email *</label>
|
||||||
|
<input type="email" name="email" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- MOBILE --}}
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Mobile No *</label>
|
||||||
|
<input type="text" name="mobile_no" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- PINCODE --}}
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Pincode</label>
|
||||||
|
<input type="text" name="pincode" class="form-control">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- ADDRESS --}}
|
||||||
|
<div class="col-md-12">
|
||||||
|
<label class="form-label">Address</label>
|
||||||
|
<textarea name="address" class="form-control" rows="2"></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- CUSTOMER TYPE --}}
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Customer Type *</label>
|
||||||
|
<select name="customer_type" class="form-select" required>
|
||||||
|
<option value="regular">Regular</option>
|
||||||
|
<option value="premium">Premium</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- STATUS --}}
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label">Status *</label>
|
||||||
|
<select name="status" class="form-select" required>
|
||||||
|
<option value="active">Active</option>
|
||||||
|
<option value="inactive">Inactive</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-end mt-4">
|
||||||
|
<a href="{{ route('admin.customers.index') }}" class="btn btn-secondary">Cancel</a>
|
||||||
|
<button class="btn btn-success">Create Customer</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endsection
|
||||||
179
resources/views/admin/customers_view.blade.php
Normal file
179
resources/views/admin/customers_view.blade.php
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
@extends('admin.layouts.app')
|
||||||
|
|
||||||
|
@section('page-title', 'Customer Details')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<div class="container py-4">
|
||||||
|
|
||||||
|
{{-- HEADER --}}
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
<h3 class="fw-bold">Customer Details</h3>
|
||||||
|
<a href="{{ route('admin.customers.index') }}" class="btn btn-secondary">
|
||||||
|
<i class="bi bi-arrow-left"></i> Back
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- CUSTOMER CARD --}}
|
||||||
|
<div class="card shadow-sm mb-4">
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<div class="d-flex align-items-center mb-3">
|
||||||
|
|
||||||
|
{{-- Avatar --}}
|
||||||
|
<div class="rounded-circle bg-primary text-white d-flex align-items-center justify-content-center me-3"
|
||||||
|
style="width:70px; height:70px; font-size:28px; font-weight:bold;">
|
||||||
|
{{ strtoupper(substr($customer->customer_name,0,1)) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 class="mb-0">{{ $customer->customer_name }}</h4>
|
||||||
|
<div class="text-muted">{{ $customer->company_name }}</div>
|
||||||
|
|
||||||
|
{{-- Customer Type --}}
|
||||||
|
@if($customer->customer_type == 'premium')
|
||||||
|
<span class="badge bg-purple mt-2">Premium Customer</span>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-secondary mt-2">Regular Customer</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ms-auto">
|
||||||
|
{{-- Status --}}
|
||||||
|
@if($customer->status == 'active')
|
||||||
|
<span class="badge bg-success p-2">Active</span>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-danger p-2">Inactive</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- BASIC INFO --}}
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h6 class="text-uppercase text-muted">Contact Information</h6>
|
||||||
|
<p class="mb-1"><strong>Email:</strong> {{ $customer->email }}</p>
|
||||||
|
<p class="mb-1"><strong>Mobile:</strong> {{ $customer->mobile_no }}</p>
|
||||||
|
<p class="mb-1"><strong>Address:</strong> {{ $customer->address }}</p>
|
||||||
|
<p class="mb-1"><strong>Pincode:</strong> {{ $customer->pincode }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h6 class="text-uppercase text-muted">Account Information</h6>
|
||||||
|
<p class="mb-1"><strong>Customer ID:</strong> {{ $customer->customer_id }}</p>
|
||||||
|
<p class="mb-1"><strong>Registered On:</strong>
|
||||||
|
{{ $customer->created_at ? $customer->created_at->format('d-m-Y') : '-' }}
|
||||||
|
</p>
|
||||||
|
<p class="mb-1"><strong>Designation:</strong>
|
||||||
|
{{ $customer->designation ?? 'N/A' }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- STATISTICS --}}
|
||||||
|
<div class="row mb-4">
|
||||||
|
|
||||||
|
{{-- Total Orders --}}
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<h5 class="fw-bold">{{ $totalOrders }}</h5>
|
||||||
|
<p class="text-muted mb-0">Total Orders</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Total Amount --}}
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<h5 class="fw-bold">₹{{ number_format($totalAmount, 2) }}</h5>
|
||||||
|
<p class="text-muted mb-0">Total Amount Spent</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Mark Count --}}
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<h5 class="fw-bold">{{ $customer->marks->count() }}</h5>
|
||||||
|
<p class="text-muted mb-0">Total Mark Numbers</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- MARK LIST --}}
|
||||||
|
<div class="card shadow-sm mb-4">
|
||||||
|
<div class="card-header bg-light">
|
||||||
|
<strong>Customer Mark Numbers</strong>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
@if($customer->marks->count() == 0)
|
||||||
|
<p class="text-muted">No mark numbers found.</p>
|
||||||
|
@else
|
||||||
|
<ul class="list-group">
|
||||||
|
@foreach($customer->marks as $mark)
|
||||||
|
<li class="list-group-item">
|
||||||
|
<strong>{{ $mark->mark_no }}</strong>
|
||||||
|
<span class="text-muted">({{ $mark->origin }} → {{ $mark->destination }})</span>
|
||||||
|
</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- {{-- RECENT ORDERS --}}
|
||||||
|
<div class="card shadow-sm mb-4">
|
||||||
|
<div class="card-header bg-light">
|
||||||
|
<strong>Recent Orders</strong>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-body p-0">
|
||||||
|
@if($recentOrders->count() == 0)
|
||||||
|
<p class="p-3 text-muted">No recent orders found.</p>
|
||||||
|
@else
|
||||||
|
<table class="table table-bordered mb-0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Order ID</th>
|
||||||
|
<th>Mark No</th>
|
||||||
|
<th>Total Amount</th>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>View</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@foreach($recentOrders as $o)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $o->order_id }}</td>
|
||||||
|
<td>{{ $o->mark_no }}</td>
|
||||||
|
<td>₹{{ number_format($o->ttl_amount, 2) }}</td>
|
||||||
|
<td>{{ $o->created_at->format('d-m-Y') }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{{ route('admin.orders.show', $o->id) }}"
|
||||||
|
class="btn btn-sm btn-primary">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endsection
|
||||||
@@ -181,7 +181,12 @@
|
|||||||
<i class="bi bi-receipt"></i> Invoice
|
<i class="bi bi-receipt"></i> Invoice
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="{{ route('admin.customers') }}" class="{{ request()->routeIs('admin.customers') ? 'active' : '' }}"><i class="bi bi-people"></i> Customers</a>
|
<a href="{{ route('admin.customers.index') }}"
|
||||||
|
class="{{ request()->routeIs('admin.customers.index') ? 'active' : '' }}">
|
||||||
|
<i class="bi bi-people"></i> Customers
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<a href="{{ route('admin.reports') }}" class="{{ request()->routeIs('admin.reports') ? 'active' : '' }}"><i class="bi bi-graph-up"></i> Reports</a>
|
<a href="{{ route('admin.reports') }}" class="{{ request()->routeIs('admin.reports') ? 'active' : '' }}"><i class="bi bi-graph-up"></i> Reports</a>
|
||||||
<a href="{{ route('admin.chat_support') }}" class="{{ request()->routeIs('admin.chat_support') ? 'active' : '' }}"><i class="bi bi-chat-dots"></i> Chat Support</a>
|
<a href="{{ route('admin.chat_support') }}" class="{{ request()->routeIs('admin.chat_support') ? 'active' : '' }}"><i class="bi bi-chat-dots"></i> Chat Support</a>
|
||||||
<!-- <a href="{{ route('admin.orders.index') }}"
|
<!-- <a href="{{ route('admin.orders.index') }}"
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use App\Http\Controllers\Admin\AdminMarkListController;
|
|||||||
use App\Http\Controllers\Admin\AdminOrderController;
|
use App\Http\Controllers\Admin\AdminOrderController;
|
||||||
use App\Http\Controllers\Admin\ShipmentController;
|
use App\Http\Controllers\Admin\ShipmentController;
|
||||||
use App\Http\Controllers\Admin\AdminInvoiceController;
|
use App\Http\Controllers\Admin\AdminInvoiceController;
|
||||||
|
use App\Http\Controllers\Admin\AdminCustomerController;
|
||||||
|
|
||||||
// -------------------------
|
// -------------------------
|
||||||
// Default Front Page
|
// Default Front Page
|
||||||
@@ -33,7 +34,7 @@ Route::prefix('admin')->middleware('auth:admin')->group(function () {
|
|||||||
Route::get('/dashboard', [AdminOrderController::class, 'index'])->name('admin.dashboard');
|
Route::get('/dashboard', [AdminOrderController::class, 'index'])->name('admin.dashboard');
|
||||||
//Route::get('/shipments', fn() => view('admin.shipments'))->name('admin.shipments');
|
//Route::get('/shipments', fn() => view('admin.shipments'))->name('admin.shipments');
|
||||||
//Route::get('/invoice', fn() => view('admin.invoice'))->name('admin.invoice');
|
//Route::get('/invoice', fn() => view('admin.invoice'))->name('admin.invoice');
|
||||||
Route::get('/customers', fn() => view('admin.customers'))->name('admin.customers');
|
//Route::get('/customers', fn() => view('admin.customers'))->name('admin.customers');
|
||||||
Route::get('/reports', fn() => view('admin.reports'))->name('admin.reports');
|
Route::get('/reports', fn() => view('admin.reports'))->name('admin.reports');
|
||||||
Route::get('/chat-support', fn() => view('admin.chat_support'))->name('admin.chat_support');
|
Route::get('/chat-support', fn() => view('admin.chat_support'))->name('admin.chat_support');
|
||||||
|
|
||||||
@@ -113,6 +114,21 @@ Route::prefix('admin')->middleware('auth:admin')->group(function () {
|
|||||||
Route::post('/invoices/{id}/update', [AdminInvoiceController::class, 'update'])
|
Route::post('/invoices/{id}/update', [AdminInvoiceController::class, 'update'])
|
||||||
->name('admin.invoices.update');
|
->name('admin.invoices.update');
|
||||||
|
|
||||||
|
// customer
|
||||||
|
Route::get('/customers', [AdminCustomerController::class, 'index'])
|
||||||
|
->name('admin.customers.index');
|
||||||
|
|
||||||
|
Route::get('/customers/{id}/view', [AdminCustomerController::class, 'view'])
|
||||||
|
->name('admin.customers.view');
|
||||||
|
|
||||||
|
Route::post('/customers/{id}/status', [AdminCustomerController::class, 'toggleStatus'])
|
||||||
|
->name('admin.customers.status');
|
||||||
|
|
||||||
|
|
||||||
|
Route::get('/customers/add', [AdminCustomerController::class, 'create'])
|
||||||
|
->name('admin.customers.add');
|
||||||
|
|
||||||
|
Route::post('/customers/store', [AdminCustomerController::class, 'store'])
|
||||||
|
->name('admin.customers.store');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user