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