License Key Required
No license key entered.
Enter or update your key with php artisan health:license <key>,
or purchase one at scriptgain.com.
Gradebook
teacher.gradebook
Compiled PHP
What Blade turns your template into. This is what the syntax check parses.
Loading…
Available Variables And Components
A guide to what this template can use, derived from the shipped source. Click any item to insert it at your cursor. It is a helpful reference, not a runtime guarantee.
Always Available
- Validation error bag. Always present. Pairs with @error('field').
In This Template
- Assignments.
- Categories.
- Enrollments.
- Grid.
- Nav.
- Section.
Drop any of these in. Click to insert the opening tag at your cursor.
General
Admin Panel
Layouts
Records
Site (Public)
Common Blade
- Print a value, safely escaped. The default choice.
- Print raw HTML. Only for content you trust.
- Show something conditionally.
- Loop over a collection.
- Loop, with a fallback when the collection is empty.
- Show a validation message for a field.
- A small block of PHP. Never on line 1. Keep logic out of templates.
- A comment that never reaches the browser.
Civic Helpers
- Build a URL to a named route, e.g. a department page.
- Link to a single news post.
- Turn a stored upload path into a public URL.
- A cache-busted URL for a bundled asset.
- Read a config value, e.g. the site width class.
- Build an absolute URL to a path.
No History Yet
Every save, revert, and reset of this template is recorded here, with a one-click way back to any of them.
The Template That Shipped With The Product
Read only. This is what Reset To Default puts back.
<x-layouts.portal :title="$section->course?->title . ' — Gradebook'" portalName="Teacher Portal" :nav="$nav">
@include('teacher._section-tabs', ['section' => $section, 'active' => 'gradebook'])
{{-- Add assignment --}}
<div x-data="{ open: false }" class="mb-6">
<button type="button" @click="open = !open"
class="inline-flex items-center gap-2 rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm font-medium text-slate-700 hover:bg-slate-50 transition">
<x-icon name="plus" class="w-4 h-4" /> Add Assignment
</button>
<div x-show="open" x-cloak class="mt-3 rounded-2xl bg-white p-5 ring-1 ring-slate-200 shadow-sm">
<form method="POST" action="{{ route('teacher.assignments.store', $section) }}" class="grid gap-4 sm:grid-cols-4">
@csrf
<x-field label="Title" for="a_title" required class="sm:col-span-2" :error="$errors->first('title')">
<x-input id="a_title" name="title" required maxlength="160" :value="old('title')" placeholder="Quiz 2" />
</x-field>
<x-field label="Category" for="a_category" :error="$errors->first('category')">
<x-select id="a_category" name="category">
@foreach ($categories as $value => $labelText)
<option value="{{ $value }}" @selected(old('category') === $value)>{{ $labelText }}</option>
@endforeach
</x-select>
</x-field>
<x-field label="Points" for="a_points" required :error="$errors->first('points_possible')">
<x-input id="a_points" name="points_possible" type="number" min="1" max="1000" step="1" :value="old('points_possible', 100)" class="tabular" />
</x-field>
<x-field label="Due" for="a_due" :error="$errors->first('due_on')">
<x-input id="a_due" name="due_on" type="date" :value="old('due_on')" />
</x-field>
<div class="sm:col-span-4"><x-button type="submit" icon="plus">Add Assignment</x-button></div>
</form>
</div>
</div>
@if ($assignments->isEmpty())
<div class="rounded-2xl bg-white p-10 text-center ring-1 ring-slate-200">
<x-icon name="clipboard" class="mx-auto w-8 h-8 text-slate-300" />
<h2 class="mt-3 font-semibold text-slate-900">No Assignments Yet</h2>
<p class="mt-1 text-sm text-slate-500">Add an assignment above, then enter grades for it here.</p>
</div>
@else
{{-- Assignment picker + one column of entry at a time: no wide table, no
sideways scroll. All inputs live in one form so Save persists every
assignment the teacher touched, not just the visible one. --}}
<form method="POST" action="{{ route('teacher.grades.save', $section) }}"
x-data="{ pick: {{ $assignments->first()->id }} }">
@csrf
<div class="mb-4 flex flex-wrap gap-2">
@foreach ($assignments as $assignment)
<button type="button" @click="pick = {{ $assignment->id }}"
class="inline-flex items-center gap-2 rounded-lg border px-3 py-1.5 text-sm font-medium transition"
:class="pick === {{ $assignment->id }} ? 'border-brand-500 bg-brand-50 text-brand-700' : 'border-slate-200 bg-white text-slate-600 hover:border-slate-300'">
{{ $assignment->title }}
<span class="text-xs text-slate-400 tabular">/{{ rtrim(rtrim($assignment->points_possible, '0'), '.') }}</span>
</button>
@endforeach
</div>
@foreach ($assignments as $assignment)
<div x-show="pick === {{ $assignment->id }}" x-cloak class="rounded-2xl bg-white ring-1 ring-slate-200 shadow-sm divide-y divide-slate-100">
<div class="flex items-center justify-between gap-3 px-5 py-3">
<div class="min-w-0">
<h3 class="font-semibold text-slate-900">{{ $assignment->title }}</h3>
<p class="text-xs text-slate-500">{{ $assignment->categoryLabel() }} · out of {{ rtrim(rtrim($assignment->points_possible, '0'), '.') }} @if ($assignment->due_on) · due {{ $assignment->due_on->format('M j') }} @endif</p>
</div>
</div>
@foreach ($enrollments as $enrollment)
<div class="flex items-center justify-between gap-3 px-5 py-2.5">
<div class="flex items-center gap-2.5 min-w-0">
<x-avatar size="sm" :initials="$enrollment->student?->initials()" :name="$enrollment->student?->name" />
<span class="truncate font-medium text-slate-800">{{ $enrollment->student?->name }}</span>
</div>
<div class="flex items-center gap-1.5 shrink-0">
<input type="number" step="0.5" min="0" max="{{ $assignment->points_possible }}"
name="scores[{{ $enrollment->id }}][{{ $assignment->id }}]"
value="{{ $grid[$enrollment->id][$assignment->id] ?? '' }}"
class="w-20 rounded-md border-0 px-2 py-1.5 text-right text-sm tabular text-slate-900 ring-1 ring-inset ring-slate-200 focus:ring-2 focus:ring-inset focus:ring-brand-500"
aria-label="{{ $enrollment->student?->name }} — {{ $assignment->title }}">
<span class="text-xs text-slate-400 tabular">/{{ rtrim(rtrim($assignment->points_possible, '0'), '.') }}</span>
</div>
</div>
@endforeach
</div>
@endforeach
<div class="mt-4 flex items-center justify-between">
<p class="text-xs text-slate-400">Switching assignments keeps your entries — Save writes them all.</p>
<x-button type="submit" icon="check">Save Grades</x-button>
</div>
</form>
@endif
</x-layouts.portal>
Blade In One Screen
The directives you will use most.
- Print a value, escaped. Safe by default.
- Print raw HTML. Only for content you trust.
- Show something conditionally.
- Loop over a collection.
- Use a shared component. Every component in Shared Components is available.
- A comment that never reaches the browser.
{{ $variable }}
{!! $html !!}
@if / @else / @endif
@foreach / @endforeach
<x-card>
{{-- comment --}}
House Rules
Follow these and your edits will survive updates.
-
Never start line 1 with
@php. Blade mis-parses it and the page fails. The editor refuses to save it. - Keep logic out of templates. If you need a calculation, it belongs in a composer or component class, not here.
- The shipped file is never modified. Reset To Default always gets you back.
- Every save is versioned. You can revert to any earlier version in one click.
- Press Tab inside the editor to indent rather than jump to the next field.