Download Laravel App
https://laravel.com/docs/12.x/installation
Connecting our Database
open .env file root directory.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=8889
DB_DATABASE=laravel12dev
DB_USERNAME=root
DB_PASSWORD=root
Database Migration
php artisan migrate
myapp>php artisan migrate
Migration table created successfully.
check database table
php artisan make:controller UsersController change it with the following codes:
app\Http\Controllers\UsersController.php
//app\Http\Controllers\UsersController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Inertia\Inertia;
use App\Models\User;
class UsersController extends Controller
{
public function home()
{
$query = User::select('id', 'name', 'email', 'created_at')->latest();
// Handle search
if (request()->has('search')) {
$search = request('search');
$query->where(function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%");
});
}
$users = $query->paginate(10);
return Inertia::render('users/index', [
'users' => $users,
'filters' => [
'search' => request('search', ''),
]
]);
}
}
Frontend with React and InertiaJS Add sidebar menu product mainNavItems from reactjs\rescourses\js\components\app-sidebar.tsx
File: pages\users\index.tsx
reactjs\resources\js\pages\users\index.tsx
//reactjs\resources\js\pages\users\index.tsx
import AppLayout from '@/layouts/app-layout';
import { type BreadcrumbItem } from '@/types';
import { Head, router } from '@inertiajs/react';
import { Button } from '@/components/ui/button';
import { Search, ChevronLeft, ChevronRight } from 'lucide-react';
import { Input } from '@/components/ui/input';
import { useState } from 'react';
interface User {
id: number;
name: string;
email: string;
created_at: string;
}
interface Props {
users: {
data: User[];
current_page: number;
last_page: number;
per_page: number;
total: number;
from: number;
to: number;
};
filters: {
search: string;
filter: string;
};
}
const breadcrumbs: BreadcrumbItem[] = [
{
title: 'Users',
href: '/admin/users',
},
];
export const generatePaginationnumber = (currentPage, totalPages) => {
if (totalPages <= 7) {
return Array.from({ length: totalPages }, (_, i) => i + 1);
}
if (currentPage <= 3) {
return [1, 2, 3 , "...", totalPages - 1, totalPages];
}
if (currentPage >= totalPages - 3) {
console.log("2");
return [1, 2, 3, "...", totalPages - 2, totalPages - 1, totalPages];
}
return [
1,
"...",
currentPage - 1,
currentPage,
currentPage + 1,
"...",
totalPages,
];
};
export default function UsersIndex({ users, filters }: Props) {
//console.log(users);
const params = new URLSearchParams(window.location.search);
const currentPage = Number(params.get("page")) || 1;
//console.log(currentPage);
const totalPages = Math.ceil(Number(users.total) / Number(users.per_page));
//const totalPages = users.total;
console.log(totalPages);
const allPages = generatePaginationnumber(currentPage, totalPages);
const [searchTerm, setSearchTerm] = useState(filters.search);
const handleSearch = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
router.get(route('users.home'), {
search: searchTerm,
}, {
preserveState: true,
preserveScroll: true,
});
};
const handlePageChange = (page: number) => {
router.get(route('users.home'), {
page,
}, {
preserveState: true,
preserveScroll: true,
});
};
return (
<AppLayout breadcrumbs={breadcrumbs}>
<Head title="Users" />
<div className="flex h-full flex-1 flex-col gap-6 rounded-xl p-6 bg-gradient-to-br from-background to-muted/20">
<div className="flex gap-4 mb-4">
<form onSubmit={handleSearch} className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input placeholder="Search name or email..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="pl-10 bg-gray-200 text-black"
/>
</form>
</div>
<div className="rounded-md border">
<div className="relative w-full overflow-auto">
<table className="w-full caption-bottom text-sm bg-white rounded-lg">
<thead>
<tr className="bg-gray-200 text-black">
<th className="py-2 px-4 text-left border-b">ID</th>
<th className="py-2 px-4 text-left border-b">Name</th>
<th className="py-2 px-4 text-left border-b">Email</th>
<th className="py-2 px-4 text-left border-b">Created At</th>
<th className="py-2 px-4 text-right border-b">Actions</th>
</tr>
</thead>
<tbody>
{users.data.map((user) => (
<tr key={user.id} className="hover:bg-gray-50 text-black">
<td className="p-4 align-middle font-medium border-b">{user.id}</td>
<td className="p-4 align-middle font-medium border-b">{user.name}</td>
<td className="p-4 align-middle font-medium border-b">{user.email}</td>
<td className="p-4 align-middle font-medium border-b">{new Date(user.created_at).toLocaleDateString()}</td>
<td className="p-4 align-middle text-right border-b">
<div className="flex justify-end gap-2">
<Button variant="ghost"
className="w-full sm:w-auto bg-blue-600 text-white rounded-lg px-4 py-2 hover:bg-blue-700"
>
Edit
</Button>
<Button variant="ghost"
className="w-full sm:w-auto bg-red-600 text-white rounded-lg px-4 py-2 hover:bg-red-700 transition transition ml-2"
>
Delete
</Button>
</div>
</td>
</tr>
))}
{users.total === 0 && (
<tr>
<td colSpan={6} className="p-4 text-center text-muted-foreground">
No users Found
</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
{/* Pagination */}
<div className="flex items-center justify-between px-2">
<div className="text-sm text-muted-foreground">
Showing {users.from} to {users.to} of {users.total} results
</div>
<div className="flex items-center space-x-2">
<Button variant="outline"
size="icon"
onClick={() => handlePageChange(users.current_page - 1)}
disabled={users.current_page === 1}
>
<ChevronLeft className="h-4 w-4" />
</Button>
<div className="flex items-center space-x-1">
{allPages.map((page, index) => (
<Button key={index}
variant={page === users.current_page ? "default" : "outline"}
size="icon"
onClick={() => handlePageChange(page)}
>
{page}
</Button>
))}
</div>
<Button variant="outline"
size="icon"
onClick={() => handlePageChange(users.current_page + 1)}
disabled={users.current_page === users.last_page}
>
<ChevronRight className="h-4 w-4" />
</Button>
</div>
</div>
</div>
</AppLayout>
);
}
Routes routes/web.php
//routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
use App\Http\Controllers\UsersController;
Route::get('/', function () {
return Inertia::render('welcome');
})->name('home');
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('dashboard', function () {
return Inertia::render('dashboard');
})->name('dashboard');
Route::get('/admin/users-pagination-search', [UsersController::class, 'home'])->name('users.home');
});
require __DIR__.'/settings.php';
require __DIR__.'/auth.php';
Run php artisan serve and npm run dev myapp>composer run dev Starting Laravel development server: http://127.0.0.1:8000
