Initial commit

This commit is contained in:
Richard Jolley committed 2026-01-14 00:54:08 +00:00
commit c909d539bc
7178 files changed
+756624

No files matched your search

@@ -0,0 +1,95 @@
<x-app-layout>
<div class="py-12">
<div class="max-w-3xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white shadow-sm sm:rounded-lg overflow-hidden">
<div class="p-6 text-gray-900">
<h1 class="text-2xl font-bold mb-6">Add New Course</h1>
{{-- Error Messages --}}
@if ($errors->any())
<div class="bg-red-100 text-red-800 p-4 rounded mb-6">
<ul class="list-disc pl-5">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('admin.courses.store') }}" method="POST" class="space-y-6">
@csrf
{{-- Subject --}}
<div>
<label for="subject_id" class="block text-sm font-medium text-gray-700 mb-1">
Subject
</label>
<select id="subject_id" name="subject_id"
class="w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-200 focus:border-blue-300"
required>
<option value="">-- Choose a subject --</option>
@foreach ($subjects as $subject)
<option value="{{ $subject->id }}"
{{ old('subject_id') == $subject->id ? 'selected' : '' }}>
{{ $subject->name }}
</option>
@endforeach
</select>
</div>
{{-- Level --}}
<div>
<label for="level_id" class="block text-sm font-medium text-gray-700 mb-1">
Level
</label>
<select id="level_id" name="level_id"
class="w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-200 focus:border-blue-300"
required>
<option value="">-- Choose a level --</option>
@foreach ($levels as $level)
<option value="{{ $level->id }}"
{{ old('level_id') == $level->id ? 'selected' : '' }}>
{{ $level->name }}
</option>
@endforeach
</select>
</div>
{{-- Lead Teacher --}}
<div>
<label for="lead_teacher" class="block text-sm font-medium text-gray-700 mb-1">
Lead Teacher
</label>
<input id="lead_teacher" type="text" name="lead_teacher"
class="w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-200 focus:border-blue-300"
value="{{ old('lead_teacher') }}" required>
</div>
{{-- Description --}}
<div>
<label for="description" class="block text-sm font-medium text-gray-700 mb-1">
Description
</label>
<textarea id="description" name="description"
class="w-full border-gray-300 rounded-md shadow-sm focus:ring-blue-200 focus:border-blue-300"
rows="4">{{ old('description') }}</textarea>
</div>
{{-- Save Button --}}
<div>
<button type="submit"
class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700
font-medium text-sm shadow-sm transition">
Save Course
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</x-app-layout>
@@ -0,0 +1,62 @@
<x-app-layout>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900">
<h1 class="text-2xl font-bold mb-4">Courses</h1>
@if (session('success'))
<div class="bg-green-100 text-green-800 p-3 rounded mb-4">
{{ session('success') }}
</div>
@endif
@if ($courses->isEmpty())
<p>No courses have been added yet.</p>
@else
<div class="overflow-x-auto">
<table class="min-w-full border border-gray-200 bg-white">
<thead class="bg-gray-100 border-b">
<tr>
<th class="px-4 py-2 text-left">ID</th>
<th class="px-4 py-2 text-left">Subject</th>
<th class="px-4 py-2 text-left">Level</th>
<th class="px-4 py-2 text-left">Lead Teacher</th>
<th class="px-4 py-2 text-left">Description</th>
<th class="px-4 py-2 text-left">Created</th>
</tr>
</thead>
<tbody>
@foreach ($courses as $course)
<tr class="border-b hover:bg-gray-50">
<td class="px-4 py-2">{{ $course->id }}</td>
<td class="px-4 py-2">
<a href="{{ route('admin.courses.show', $course) }}">
{{ $course->subject->name }}
</a>
</td>
<td class="px-4 py-2">
{{ $course->level ? $course->level->name : '—' }}
</td>
<td class="px-4 py-2">{{ $course->lead_teacher }}</td>
<td class="px-4 py-2">{{ $course->description }}</td>
<td class="px-4 py-2">{{ $course->created_at->format('Y-m-d') }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endif
<div class="mt-6">
<a href="{{ route('admin.courses.create') }}"
class="px-4 py-2 bg-gray-200 border border-gray-300 rounded-md
font-semibold text-sm text-black hover:bg-gray-300
focus:outline-none focus:ring focus:ring-gray-400 transition">
Add New Course
</a>
</div>
</div>
</div>
</div>
</div>
</x-app-layout>
@@ -0,0 +1,192 @@
<x-app-layout>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white shadow-sm sm:rounded-lg overflow-hidden">
<div class="p-6 text-gray-900">
<h1 class="text-2xl font-bold mb-6">
Manage Course: {{ $course->subject->name }} ({{ $course->level->name }})
</h1>
@forelse($course->modules as $module)
<div class="mb-10">
<!-- Module Name -->
<h2 class="text-xl font-semibold mb-4">
{{ $module->name }}
</h2>
<div class="bg-gray-50 border rounded-lg p-5">
<!-- SECTION HEADER + ADD FORM -->
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-semibold">
Lesson Sections
</h3>
<form action="{{ route('admin.sections.store', ['course' => $course->slug]) }}"
method="POST"
class="flex items-center gap-2">
@csrf
<input type="hidden" name="module_id" value="{{ $module->id }}">
<input type="text"
name="title"
placeholder="New Section Title"
required
class="border rounded px-2 py-1 text-sm w-48 focus:ring-blue-200 focus:border-blue-300">
<button type="submit"
class="px-3 py-1 bg-green-100 text-green-700 rounded hover:bg-green-200 text-sm font-medium">
➕ Add
</button>
</form>
</div>
<!-- SECTION LIST -->
<ul id="section-list-{{ $module->id }}"
class="border rounded divide-y divide-gray-200 sortable-item bg-white">
@foreach($module->lessonSections->sortBy('order') as $section)
<li class="flex items-center justify-between px-4 py-2 hover:bg-gray-50"
data-id="{{ $section->id }}">
<!-- Drag handle + link -->
<div class="flex items-center gap-3">
<span class="cursor-move text-gray-400 select-none">⋮⋮</span>
<a href="{{ route('admin.sections.show', [
'course' => $course->slug,
'section' => $section->slug
]) }}"
class="text-blue-600 hover:underline">
{{ $section->title }}
</a>
</div>
<!-- Rename + Delete -->
<div class="flex items-center gap-2">
<!-- RENAME -->
<form action="{{ route('admin.sections.update', [
'course' => $course->slug,
'lessonSection' => $section->slug
]) }}"
method="POST"
class="flex items-center gap-1">
@csrf
@method('PUT')
<input type="text"
name="title"
value="{{ $section->title }}"
class="border border-gray-300 rounded px-2 py-0.5 text-sm w-40 focus:ring-blue-200 focus:border-blue-300">
<button type="submit"
class="text-blue-600 hover:text-blue-800 text-sm">
✔
</button>
</form>
<!-- DELETE -->
<button onclick="if (confirmDelete('{{ $section->title }}')) document.getElementById('delete-section-{{ $section->id }}').submit();"
class="text-red-600 hover:text-red-800 text-sm">
✖
</button>
</div>
<!-- SINGLE DELETE FORM (correct route, no duplicates) -->
<form id="delete-section-{{ $section->id }}"
action="{{ route('admin.sections.destroy', [
'course' => $course->slug,
'section' => $section->slug
]) }}"
method="POST"
class="hidden">
@csrf
@method('DELETE')
</form>
</li>
@endforeach
</ul>
<!-- Hidden reorder field + button -->
<button form="reorderForm-{{ $module->id }}"
class="mt-3 px-3 py-1 bg-blue-100 text-blue-700 rounded hover:bg-blue-200 text-sm font-medium">
💾 Save Section Order
</button>
<form action="{{ route('admin.sections.reorder', ['course' => $course->slug]) }}"
method="POST"
id="reorderForm-{{ $module->id }}"
class="hidden">
@csrf
<input type="hidden" name="order" id="reorderInput-{{ $module->id }}">
</form>
</div>
</div>
@empty
<p class="text-gray-600">
No modules yet.
<a href="{{ route('admin.modules.create') }}" class="text-blue-600 hover:underline">
Add a module
</a>
</p>
@endforelse
<!-- Add New Module -->
<div class="mt-8 bg-gray-50 border rounded-lg p-5">
<h3 class="text-lg font-semibold mb-4">Add a New Module</h3>
<form action="{{ route('admin.modules.store') }}" method="POST" class="flex gap-3">
@csrf
<input type="hidden" name="course_id" value="{{ $course->id }}">
<input type="text"
name="name"
class="flex-1 border-gray-300 rounded-md shadow-sm focus:ring focus:ring-blue-200"
placeholder="Module Name"
required>
<button type="submit"
class="px-3 py-1 bg-green-100 text-green-700 rounded hover:bg-green-200 text-sm font-medium">
➕ Add Module
</button>
</form>
</div>
</div>
</div>
</div>
</div>
</x-app-layout>
<!-- Sortable -->
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js"></script>
<script>
// Reorder handling
document.querySelectorAll('[id^="section-list-"]').forEach(list => {
const moduleId = list.id.replace('section-list-', '');
const reorderForm = document.getElementById('reorderForm-' + moduleId);
const reorderInput = document.getElementById('reorderInput-' + moduleId);
new Sortable(list, { animation: 150 });
reorderForm.addEventListener('submit', function () {
const ids = [...list.querySelectorAll('li')].map(li => li.dataset.id);
reorderInput.value = JSON.stringify(ids);
});
});
function confirmDelete(name) {
return confirm(
`Are you sure you want to delete the lesson section "${name}"?\n\n` +
`⚠️ All chapters and lessons inside it will also be deleted.`
);
}
</script>