Reputation: 16311
Just started experimenting with Laravel 9 (Inertia + React) and wanted to set up user roles. I tried following the steps in this guide and got it working but now the login/register links on my Navbar layer stops working. The logout link works fine however.
Directly typing and going to 127.0.0.1/login
or 127.0.0.1/register
works fine and the routes load as they should but clicking the links doesn't do anything (the progress bar moves but after it fills up, nothing happens).
What is causing this? Snippets of my auth.php
, web.php
, navbar layer and the authenticated/guest layers provided below. Other than the changes shown in the guide and the following files, everything else is default:
use App\Http\Controllers\Auth\AuthenticatedSessionController;
use App\Http\Controllers\Auth\ConfirmablePasswordController;
use App\Http\Controllers\Auth\EmailVerificationNotificationController;
use App\Http\Controllers\Auth\EmailVerificationPromptController;
use App\Http\Controllers\Auth\NewPasswordController;
use App\Http\Controllers\Auth\PasswordResetLinkController;
use App\Http\Controllers\Auth\RegisteredUserController;
use App\Http\Controllers\Auth\VerifyEmailController;
use Illuminate\Support\Facades\Route;
Route::middleware('guest')->group(function () {
Route::get('register', [RegisteredUserController::class, 'create'])
->name('register');
Route::post('register', [RegisteredUserController::class, 'store']);
Route::get('login', [AuthenticatedSessionController::class, 'create'])
->name('login');
Route::post('login', [AuthenticatedSessionController::class, 'store']);
Route::get('forgot-password', [PasswordResetLinkController::class, 'create'])
->name('password.request');
Route::post('forgot-password', [PasswordResetLinkController::class, 'store'])
->name('password.email');
Route::get('reset-password/{token}', [NewPasswordController::class, 'create'])
->name('password.reset');
Route::post('reset-password', [NewPasswordController::class, 'store'])
->name('password.update');
});
Route::middleware('auth')->group(function () {
Route::get('verify-email', [EmailVerificationPromptController::class, '__invoke'])
->name('verification.notice');
Route::get('verify-email/{id}/{hash}', [VerifyEmailController::class, '__invoke'])
->middleware(['signed', 'throttle:6,1'])
->name('verification.verify');
Route::post('email/verification-notification', [EmailVerificationNotificationController::class, 'store'])
->middleware('throttle:6,1')
->name('verification.send');
Route::get('confirm-password', [ConfirmablePasswordController::class, 'show'])
->name('password.confirm');
Route::post('confirm-password', [ConfirmablePasswordController::class, 'store']);
Route::post('logout', [AuthenticatedSessionController::class, 'destroy'])
->name('logout');
});
use App\Http\Controllers\Auth\RedirectAuthenticatedUsersController;
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
Route::get('/', function () {
return Inertia::render('Welcome', [
'canLogin' => Route::has('login'),
'canRegister' => Route::has('register'),
'laravelVersion' => Application::VERSION,
'phpVersion' => PHP_VERSION,
]);
});
// Route::get('/dashboard', function () {
// return Inertia::render('Dashboard');
// })->middleware(['auth', 'verified'])->name('dashboard');
Route::group(['middleware' => 'auth'], function() {
Route::inertia('/dashboard', 'Dashboard')->name('dashboard');
Route::get("/redirectAuthenticatedUsers", [RedirectAuthenticatedUsersController::class, "home"]);
Route::group(['middleware' => 'checkRole:admin'], function() {
Route::inertia('/adminDashboard', 'AdminDashboard')->name('adminDashboard');
});
Route::group(['middleware' => 'checkRole:user'], function() {
Route::inertia('/userDashboard', 'UserDashboard')->name('userDashboard');
});
Route::group(['middleware' => 'checkRole:guest'], function() {
Route::inertia('/guestDashboard', 'GuestDashboard')->name('guestDashboard');
});
});
import React, { useState } from 'react';
import ApplicationLogo from '@/Components/ApplicationLogo';
import { Link, usePage } from '@inertiajs/inertia-react';
import Dropdown from '@/Components/Dropdown';
import ResponsiveNavLink from '@/Components/ResponsiveNavLink';
export default function Navbar({ children }) {
const { auth } = usePage().props
const [showingNavigationDropdown, setShowingNavigationDropdown] = useState(false);
return (
<>
<nav className="bg-white border-b border-gray-100">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-16">
<div className="flex">
<div className="shrink-0 flex items-center">
<Link href="/">
<ApplicationLogo className="block h-9 w-auto text-gray-500" />
</Link>
<span className="font-semibold text-xl tracking-tight">DrewL Dashboard</span>
</div>
</div>
<div className="hidden sm:flex sm:items-center sm:ml-6">
<div className="ml-3 relative">
<Dropdown>
<Dropdown.Trigger>
<span className="inline-flex rounded-md">
<button
type="button"
className="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 bg-white hover:text-gray-700 focus:outline-none transition ease-in-out duration-150"
>
{auth.user ? (
auth.user.name
) : (
<>
Log In/Register
</>
)}
<svg
className="ml-2 -mr-0.5 h-4 w-4"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clipRule="evenodd"
/>
</svg>
</button>
</span>
</Dropdown.Trigger>
{auth.user ? (
<Dropdown.Content>
<Dropdown.Link href={route('logout')} method="post" as="button">
Log Out
</Dropdown.Link>
</Dropdown.Content>
) : (
<Dropdown.Content>
<Dropdown.Link href={route('login')} as="button">
Log in
</Dropdown.Link>
<Dropdown.Link href={route('register')} as="button">
Register
</Dropdown.Link>
</Dropdown.Content>
)}
</Dropdown>
</div>
</div>
<div className="-mr-2 flex items-center sm:hidden">
<button
onClick={() => setShowingNavigationDropdown((previousState) => !previousState)}
className="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-500 transition duration-150 ease-in-out"
>
<svg className="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
<path
className={!showingNavigationDropdown ? 'inline-flex' : 'hidden'}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M4 6h16M4 12h16M4 18h16"
/>
<path
className={showingNavigationDropdown ? 'inline-flex' : 'hidden'}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
</div>
</div>
<div className={(showingNavigationDropdown ? 'block' : 'hidden') + ' sm:hidden'}>
<div className="pt-4 pb-1 border-t border-gray-200">
<div className="px-4">
<div className="font-medium text-base text-gray-800">Welcome</div>
<div className="font-medium text-sm text-gray-500">Login now</div>
</div>
<div className="mt-3 space-y-1">
{auth.user ? (
<ResponsiveNavLink href={route('logout')} as="button" method="post" className="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-teal-500 hover:bg-white mt-4 lg:mt-0">
Log out
</ResponsiveNavLink>
) : (
<>
<ResponsiveNavLink href={route('register')} as="button" method="post" className="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-teal-500 hover:bg-white mt-4 lg:mt-0">
Register
</ResponsiveNavLink>
<ResponsiveNavLink href={route('login')} as="button" method="post" className="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-teal-500 hover:bg-white mt-4 lg:mt-0">
Log in
</ResponsiveNavLink>
</>
)}
</div>
</div>
</div>
</nav>
{children}
</>
);
}
import React from 'react';
import Navbar from '@/Layouts/Shared/Navbar.jsx';
export default function Authenticated({ auth, header, children }) {
return (
<Navbar>
<div className="min-h-screen bg-gray-100">
{header && (
<header className="bg-white shadow">
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">{header}</div>
</header>
)}
<main>{children}</main>
</div>
</Navbar>
);
}
import React from 'react';
import ApplicationLogo from '@/Components/ApplicationLogo';
import { Link } from '@inertiajs/inertia-react';
import Navbar from '@/Layouts/Shared/Navbar.jsx';
export default function Guest({ children }) {
return (
<Navbar>
<div className="min-h-screen bg-gray-100">
<div className="min-h-screen flex flex-col sm:justify-center items-center pt-0 bg-gray-100">
<div>
<Link href="/">
<ApplicationLogo className="w-20 h-20 fill-current text-gray-500" />
</Link>
</div>
<div className="w-full sm:max-w-md mt-6 px-6 py-4 bg-white shadow-md overflow-hidden sm:rounded-lg">
{children}
</div>
</div>
</div>
</Navbar>
);
}
Upvotes: 0
Views: 2217
Reputation: 16311
Figured it out. The problem was because I was specifying the method for both login/register as POST requests instead of GET requests. Changing the method for both login and register to GET (as shown below) fixed the issue.
<Dropdown.Link href={route('login')} method="get" as="button">
Log in
</Dropdown.Link>
<Dropdown.Link href={route('register')} method="get" as="button">
Register
</Dropdown.Link>
Upvotes: 1