Back to Course |
[Mini-Course] Laravel 11: Breeze with User Role Areas

Separating Teacher and Student Layouts

Now, let's create a page for a teacher and call it a timetable. I deliberately chose the same page name: so it would be the student and teacher timetables for all the classes, but separated in the folders/namespaces

The name is the same, but the purpose and what will be on the page would be radically different.


Teacher: Timetable Controller and View

First, let's generate the Controller. And again, we must specify a namespace.

php artisan make:controller Teacher/TimetableController

We have two timetable Controllers, which are separated in the subfolder or the namespace.

Now, let's add the index() method to the Controller and create a View with different text. The View file will be in the teacher folder.

app/Http/Controllers/Teacher/TimetableController.php:

use Illuminate\Contracts\View\View;
use App\Http\Controllers\Controller;
 
class TimetableController extends Controller
{
public function index(): View
{
return view('teacher.timetable');
}
}

resources/views/teacher/timetable.php:

<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
{{ __('Timetable') }}
</h2>
</x-slot>
 
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900 dark:text-gray-100">
{{ __("Teacher's Timetable coming soon.") }}
</div>
</div>
</div>
</div>
</x-app-layout>

Teacher Route Group

We need to create a new Route by creating a Route group for the teacher that is similar to what we have for the student.

routes/web.php:

Route::get('/', function () {
return view('welcome');
});
 
Route::middleware(['auth', 'verified'])->group(function () {
Route::prefix('student')
->name('student.')
->group(function () {
Route::get('timetable', [\App\Http\Controllers\Student\TimetableController::class, 'index'])
->name('timetable');
});
 
Route::prefix('teacher')
->name('teacher.')
->group(function () {
Route::get('timetable', [\App\Http\Controllers\Teacher\TimetableController::class, 'index'])
->name('timetable');
});
});
 
Route::middleware('auth')->group(function () {
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
});
 
require __DIR__ . '/auth.php';

After visiting the /teacher/timetable, we see the correct page for the teacher.


Design Layouts: Student

Both timetable pages use the same x-app-layout Blade component from Laravel Breeze. We need to create three layouts from this app layout.

So, using your editor, use the Save As feature for the app/View/Components/AppLayout.php file and name it StudentLayout.php and TeacherLayout.php.

Remember to set the correct class name as the filenames. Next, we must change the View file rendered in these two classes.

app/View/Components/StudentLayout.blade.php:

use Illuminate\View\View;
use Illuminate\View\Component;
 
class StudentLayout extends Component
{
public function render(): View
{
return view('layouts.student');
}
}

app/View/Components/TeacherLayout.blade.php:

use Illuminate\View\Component;
use Illuminate\View\View;
 
class TeacherLayout extends Component
{
public function render(): View
{
return view('layouts.teacher');
}
}

The View files can also be created from the original resources/views/layouts/app.blade.php using the Save As option or manually copying the content.

Also, we will have different navigation for each layout. For that, we will move the navigation to a folder in resources/views/layouts/navigation and call it by the same name as the layout.

So, first, let's move the resources/views/layouts/navigation.blade.php to the resources/views/layouts/navigation folder and rename it to student.blade.php. Now, we must use this navigation in the student layout.

resources/views/layouts/student.blade.php:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
// ...
</head>
<body class="font-sans antialiased">
<div class="min-h-screen bg-gray-100 dark:bg-gray-900">
@include('layouts.navigation') {{-- [tl! --] --}}
@include('layouts.navigation.student') {{-- [tl! ++] --}}
 
// ...
</div>
</body>
</html>

Finally, we can change the layout for the student timetable page.

resources/views/student/timetable.blade.php:

<x-app-layout>
<x-student-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
{{ __('Timetable') }}
</h2>
</x-slot>
 
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900 dark:text-gray-100">
{{ __('Timetable coming soon.') }}
</div>
</div>
</div>
</div>
</x-app-layout>
</x-student-layout>

After visiting the /student/timetable page, we can see that it is the same, but structurally, it has a different layout.


Design Layout: Teacher

Now, let's repeat the same for the teacher layout. First, we will set the navigation.

resources/views/layouts/teacher.blade.php:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
// ...
</head>
<body class="font-sans antialiased">
<div class="min-h-screen bg-gray-100 dark:bg-gray-900">
@include('layouts.navigation')
@include('layouts.navigation.teacher')
 
// ...
</div>
</body>
</html>

In the navigation, we must change the Route names from student to teacher.

resources/views/layouts/navigation/teacher.blade.php:

<nav x-data="{ open: false }" class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700">
// ...
<!-- Navigation Links -->
<div class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex">
<x-nav-link :href="route('student.timetable')" :active="request()->routeIs('student.timetable')">
<x-nav-link :href="route('teacher.timetable')" :active="request()->routeIs('teacher.timetable')">
{{ __('Timetable') }}
</x-nav-link>
</div>
// ...
</nav>

And now we can also change the layout for the teacher's timetable page.

resources/views/teacher/timetable.blade.php:

<x-app-layout>
<x-teacher-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
{{ __('Timetable') }}
</h2>
</x-slot>
 
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900 dark:text-gray-100">
{{ __("Teacher's Timetable coming soon.") }}
</div>
</div>
</div>
</div>
</x-app-layout>
</x-teacher-layout>

If you have any files left from the App Layout, you can delete them now.

Now, you have separate layouts, navigations, and everything.

But wait, visually the designs are absolutely identical!


Change Layout Background Color

In this course we won't be building any fancy designs, but to see some visual changes, we can change the background for one of the layouts.

resources/views/layouts/teacher.blade.php:

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
// ...
<body class="font-sans antialiased">
<div class="min-h-screen bg-gray-100 dark:bg-gray-900">
<div class="min-h-screen bg-amber-50 dark:bg-gray-900">
// ...
</div>
</body>
</html>

After using different classes from Tailwind CSS, remember to recompile using npm run dev or npm run build.

The teacher timetable page now has a yellow background instead of gray.


The main point of this lesson was to have two different files as a layout. Now, these layouts can look completely different.