admin set 3

This commit is contained in:
imadhigp 2026-08-07 09:07:35 +05:30
parent d24235a2b7
commit db3373002d
7 changed files with 167 additions and 118 deletions

View File

@ -8,24 +8,35 @@ use Illuminate\Support\Facades\Hash;
class AdminAuthController extends Controller class AdminAuthController extends Controller
{ {
/**
* Admin Login View එක පෙන්වීම
*/
public function showLoginForm() public function showLoginForm()
{ {
return view('adminlogin'); return view('adminlogin');
} }
/**
* Admin Login Process එක සිදු කිරීම
*/
public function login(Request $request) public function login(Request $request)
{ {
// 1. Validation සිදු කිරීම
$request->validate([ $request->validate([
'username' => 'required', 'username' => 'required',
'password' => 'required', 'password' => 'required',
]); ]);
// 2. Database එකෙන් Admin පරීක්ෂා කිරීම
$admin = DB::table('adminlogins')->where('username', $request->username)->first(); $admin = DB::table('adminlogins')->where('username', $request->username)->first();
// 3. Password එක හරියටම ගැලපේ නම්
if ($admin && Hash::check($request->password, $admin->password)) { if ($admin && Hash::check($request->password, $admin->password)) {
// Session Fixation ආරක්ෂාව සඳහා Session ID එක Regenerate කිරීම
$request->session()->regenerate();
// Session එකට Admin Data තැන්පත් කිරීම
session([ session([
'admin_id' => $admin->id, 'admin_id' => $admin->id,
'admin_username' => $admin->username 'admin_username' => $admin->username
@ -34,24 +45,28 @@ class AdminAuthController extends Controller
return response()->json([ return response()->json([
'success' => true, 'success' => true,
'message' => 'Login Successful!', 'message' => 'Login Successful!',
'redirect_url' => url('admin/adminmycourese') 'redirect_url' => route('admin.mycourses') // නැතහොත් route('admin.admindashboard')
]); ]);
} }
// 4. Username හෝ Password වැරදි නම්
return response()->json([ return response()->json([
'success' => false, 'success' => false,
'message' => 'Wrong Username or Password!' 'message' => 'Wrong Username or Password!'
], 401); ], 401);
} }
/**
* Admin Logout Process එක සිදු කිරීම
*/
public function logout(Request $request) public function logout(Request $request)
{ {
// 1. Session එකෙන් Admin දත්ත ඉවත් කර Session එක Invalidate කිරීම // 1. Session එකෙන් Data ඉවත් කර Session එක Invalidate කිරීම
$request->session()->forget(['admin_id', 'admin_username']); $request->session()->forget(['admin_id', 'admin_username']);
$request->session()->invalidate(); $request->session()->invalidate();
$request->session()->regenerateToken(); $request->session()->regenerateToken();
// 2. Request එක AJAX / JSON එකක් නම් JSON Response එකක් යැවීම // 2. Request එක AJAX / JSON නම් JSON Response එකක් යැවීම
if ($request->ajax() || $request->wantsJson()) { if ($request->ajax() || $request->wantsJson()) {
return response()->json([ return response()->json([
'success' => true, 'success' => true,
@ -59,7 +74,7 @@ public function logout(Request $request)
]); ]);
} }
// 3. Normal Form submit එකක් නම් කෙලින්ම Login page එකට Redirect කිරීම // 3. Normal Form Submit එකක් නම් Redirect කිරීම
return redirect()->route('admin.login')->with('success', 'Logged out successfully!'); return redirect()->route('admin.login')->with('success', 'Logged out successfully!');
} }
} }

View File

@ -17,7 +17,7 @@ class AdminTimetableController extends Controller
// DB එකේ තියෙන ඔක්කොම Timetable entries ගන්නවා // DB එකේ තියෙන ඔක්කොම Timetable entries ගන්නවා
$allTimetables = Timetable::all(); $allTimetables = Timetable::all();
// ඊට පස්සේ Time Slot එකයි Day එකයි අනුව Map කරගන්නවා // Time Slot එකයි Day එකයි අනුව Grid Map කරගන්නවා
$grid = []; $grid = [];
foreach ($allTimetables as $item) { foreach ($allTimetables as $item) {
$grid[$item->time_slot][$item->day] = $item; $grid[$item->time_slot][$item->day] = $item;
@ -25,11 +25,12 @@ class AdminTimetableController extends Controller
$days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']; $days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'];
// Image එකේ තියෙන Exact Time Slots
$timeSlots = [ $timeSlots = [
'08:30 - 10:00', '08:30 - 10:30',
'10:45 - 12:15', '10:45 - 12:30',
'12:15 - 01:00', // Lunch / Interval '12:30 - 01:30', // Lunch / Rest Time
'01:00 - 03:00' '01:30 - 03:30'
]; ];
// Today's Day Name // Today's Day Name
@ -39,6 +40,7 @@ class AdminTimetableController extends Controller
return view('admin.admintimetable', compact('allTimetables', 'days', 'timeSlots', 'grid', 'todaySchedule', 'today')); return view('admin.admintimetable', compact('allTimetables', 'days', 'timeSlots', 'grid', 'todaySchedule', 'today'));
} }
// Save or Update Entry
// Save or Update Entry // Save or Update Entry
public function store(Request $request) public function store(Request $request)
{ {
@ -49,7 +51,7 @@ class AdminTimetableController extends Controller
'type' => 'required|string', 'type' => 'required|string',
]); ]);
// අදාළ Day එකටයි Time Slot එකටයි කලින් Data තිබුණොත් Update කරනවා, නැත්නම් අලුතෙන් Add කරනවා // student_log_id පේළිය ඉවත් කර ඇත
Timetable::updateOrCreate( Timetable::updateOrCreate(
[ [
'day' => $request->day, 'day' => $request->day,
@ -58,13 +60,13 @@ class AdminTimetableController extends Controller
[ [
'subject_name' => $request->subject_name, 'subject_name' => $request->subject_name,
'type' => $request->type, 'type' => $request->type,
'student_log_id' => $request->student_log_id,
] ]
); );
return redirect()->back()->with('success', 'Timetable updated successfully!'); return redirect()->back()->with('success', 'Timetable saved successfully!');
} }
// Delete Single Slot // Delete Single Slot
public function destroy($id) public function destroy($id)
{ {

View File

@ -10,19 +10,14 @@ class TimetableController extends Controller
{ {
public function index() public function index()
{ {
$studentLogId = session('student_log_id') ?? session('student_id'); $studentLogId = session('student_log_id') ?? session('student_id');
if (!$studentLogId) { if (!$studentLogId) {
return redirect('/signin')->with('error', 'Please login first!'); return redirect('/signin')->with('error', 'Please login first!');
} }
// DB එකේ නැති student_log_id සහ sort_order query එකෙන් ඉවත් කර ඇත
$rawTimetables = Timetable::whereNull('student_log_id') $rawTimetables = Timetable::all();
->orWhere('student_log_id', $studentLogId)
->orderBy('sort_order', 'asc')
->get();
$schedule = []; $schedule = [];
$timeSlots = []; $timeSlots = [];
@ -34,15 +29,10 @@ class TimetableController extends Controller
$schedule[$item->time_slot][$item->day] = $item; $schedule[$item->time_slot][$item->day] = $item;
} }
// Today's Schedule (දැනට ඇති columns වලින් පමණක් Filter කර ඇත)
$todayName = Carbon::now()->format('l'); $todayName = Carbon::now()->format('l');
$todaySchedule = Timetable::where('day', $todayName) $todaySchedule = Timetable::where('day', $todayName)
->where(function($q) use ($studentLogId) {
$q->whereNull('student_log_id')
->orWhere('student_log_id', $studentLogId);
})
->where('type', '!=', 'Break') ->where('type', '!=', 'Break')
->orderBy('sort_order', 'asc')
->get(); ->get();
$days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']; $days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'];

View File

@ -102,15 +102,20 @@ class adminmycoursesController extends Controller
} }
// 4. Course එක Delete කිරීම (Delete) // 4. Course එක Delete කිරීම (Delete)
// Course එක Delete කිරීම (Delete)
public function destroy($id) public function destroy($id)
{ {
$course = DB::table('courses')->where('id', $id)->first(); $course = DB::table('courses')->where('id', $id)->first();
if ($course) { if ($course) {
// Image එක Storage එකෙන් Delete කිරීම
if ($course->image && Storage::disk('public')->exists($course->image)) { if ($course->image && Storage::disk('public')->exists($course->image)) {
Storage::disk('public')->delete($course->image); Storage::disk('public')->delete($course->image);
} }
// Database record එක Delete කිරීම
DB::table('courses')->where('id', $id)->delete(); DB::table('courses')->where('id', $id)->delete();
return redirect()->back()->with('success', 'Course deleted successfully!'); return redirect()->back()->with('success', 'Course deleted successfully!');
} }

View File

@ -300,6 +300,7 @@
</button> </button>
<!-- Delete Form --> <!-- Delete Form -->
<form action="{{ route('admin.courses.delete', $course->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this course?')"> <form action="{{ route('admin.courses.delete', $course->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this course?')">
@csrf @csrf
@method('DELETE') @method('DELETE')

View File

@ -9,29 +9,59 @@
color: white; color: white;
border-radius: 12px; border-radius: 12px;
} }
/* Badge Colors based on UI design */
.badge-theory { background-color: #1e293b; color: #ffffff; } /* Badge Colors matching the design */
.badge-practical { background-color: #881337; color: #ffffff; } .badge-type {
.badge-workshop { background-color: #c2410c; color: #ffffff; } font-size: 11px;
font-weight: 600;
padding: 3px 12px;
border-radius: 12px;
letter-spacing: 0.3px;
display: inline-block;
}
.badge-theory { background-color: #1e2035; color: #ffffff; }
.badge-practical { background-color: #6b1d1d; color: #ffffff; }
.badge-workshop { background-color: #ea580c; color: #ffffff; }
.badge-exam { background-color: #ca8a04; color: #ffffff; } .badge-exam { background-color: #ca8a04; color: #ffffff; }
/* Table Custom Styles */
.table-timetable {
border-collapse: separate;
border-spacing: 0;
border: 1px solid #e2e8f0;
border-radius: 10px;
overflow: hidden;
}
.table-timetable th { .table-timetable th {
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
font-weight: 600; font-weight: 700;
padding: 12px; padding: 14px 10px;
color: #334155;
background-color: #f8fafc;
border-bottom: 1px solid #e2e8f0;
} }
.table-timetable td { .table-timetable td {
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
height: 85px; height: 90px;
position: relative; padding: 6px;
border-bottom: 1px solid #e2e8f0;
border-right: 1px solid #e2e8f0;
} }
.table-timetable tr:last-child td {
border-bottom: none;
}
.table-timetable td:last-child {
border-right: none;
}
/* Cell Hover & Click */
.timetable-cell { .timetable-cell {
cursor: pointer; cursor: pointer;
padding: 8px; padding: 8px;
border-radius: 6px; border-radius: 8px;
transition: background-color 0.2s; transition: all 0.2s ease-in-out;
height: 100%; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -39,10 +69,13 @@
align-items: center; align-items: center;
} }
.timetable-cell:hover { .timetable-cell:hover {
background-color: #e2e8f0; background-color: #f1f5f9;
transform: translateY(-1px);
} }
/* Today's Red Header Highlight */
.today-header { .today-header {
background-color: #dc2626 !important; background-color: #d9383a !important;
color: white !important; color: white !important;
} }
</style> </style>
@ -78,8 +111,8 @@
@forelse($todaySchedule as $item) @forelse($todaySchedule as $item)
<div class="p-3 mb-2 bg-light rounded border-start border-4 border-danger d-flex justify-content-between align-items-center"> <div class="p-3 mb-2 bg-light rounded border-start border-4 border-danger d-flex justify-content-between align-items-center">
<div> <div>
<span class="badge badge-{{ strtolower($item->type) }} mb-1">{{ $item->type }}</span> <span class="badge badge-type badge-{{ strtolower($item->type) }} mb-1">{{ $item->type }}</span>
<h6 class="fw-bold mb-0">{{ $item->subject_name }}</h6> <h6 class="fw-bold mb-0 text-dark">{{ $item->subject_name }}</h6>
</div> </div>
<small class="text-muted fw-bold">{{ $item->time_slot }}</small> <small class="text-muted fw-bold">{{ $item->time_slot }}</small>
</div> </div>
@ -100,14 +133,14 @@
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="d-flex flex-wrap gap-2 mb-3"> <div class="d-flex flex-wrap gap-2 mb-3">
<span class="badge badge-theory px-3 py-2">Theory</span> <span class="badge badge-type badge-theory">Theory</span>
<span class="badge badge-practical px-3 py-2">Practical</span> <span class="badge badge-type badge-practical">Practical</span>
<span class="badge badge-workshop px-3 py-2">Workshop</span> <span class="badge badge-type badge-workshop">Workshop</span>
<span class="badge badge-exam px-3 py-2">Exam</span> <span class="badge badge-type badge-exam">Exam</span>
</div> </div>
<hr> <hr>
<p class="text-muted small mb-0"> <p class="text-muted small mb-0">
<i class="fa-solid fa-hand-pointer me-1 text-primary"></i> <strong>How to Edit:</strong> Click on any timetable slot in the table below to edit or add subject details. <i class="fa-solid fa-hand-pointer me-1 text-primary"></i> <strong>How to Edit / Add:</strong> Click on any timetable slot in the table below to add or edit class details.
</p> </p>
</div> </div>
</div> </div>
@ -116,10 +149,10 @@
<!-- Main Timetable Grid --> <!-- Main Timetable Grid -->
<div class="card border-0 shadow-sm rounded-3"> <div class="card border-0 shadow-sm rounded-3">
<div class="card-body p-0"> <div class="card-body p-3">
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-bordered table-timetable mb-0 align-middle"> <table class="table table-timetable mb-0 align-middle">
<thead class="table-light"> <thead>
<tr> <tr>
<th style="width: 15%;">Time</th> <th style="width: 15%;">Time</th>
@foreach($days as $day) @foreach($days as $day)
@ -133,12 +166,12 @@
@foreach($timeSlots as $slot) @foreach($timeSlots as $slot)
<tr> <tr>
<!-- Time Column --> <!-- Time Column -->
<td class="fw-bold text-secondary bg-light">{{ $slot }}</td> <td class="fw-bold text-secondary bg-light" style="font-size: 13px;">{{ $slot }}</td>
@if($slot == '12:15 - 01:00') @if($slot == '12:30 - 01:30')
<!-- Interval Row --> <!-- Lunch / Rest Time Row -->
<td colspan="5" class="bg-light text-center fw-bold text-muted py-3"> <td colspan="5" class="bg-light text-center fw-bold text-secondary py-3" style="letter-spacing: 0.5px;">
Interval / Lunch Break 🍱 LUNCH BREAK / REST TIME
</td> </td>
@else @else
<!-- Days Columns --> <!-- Days Columns -->
@ -146,19 +179,19 @@
@php @php
$item = $grid[$slot][$day] ?? null; $item = $grid[$slot][$day] ?? null;
@endphp @endphp
<td class="p-1"> <td>
<div class="timetable-cell" <div class="timetable-cell"
data-bs-toggle="modal" data-bs-toggle="modal"
data-bs-target="#editSlotModal" data-bs-target="#editSlotModal"
onclick="openEditModal('{{ $day }}', '{{ $slot }}', '{{ $item->subject_name ?? '' }}', '{{ $item->type ?? 'Theory' }}', '{{ $item->id ?? '' }}')"> onclick="openEditModal('{{ $day }}', '{{ $slot }}', '{{ $item->subject_name ?? '' }}', '{{ $item->type ?? 'Theory' }}', '{{ $item->id ?? '' }}')">
@if($item) @if($item)
<span class="badge badge-{{ strtolower($item->type) }} mb-1"> <span class="badge badge-type badge-{{ strtolower($item->type) }} mb-1">
{{ $item->type }} {{ $item->type }}
</span> </span>
<div class="fw-bold text-dark small">{{ $item->subject_name }}</div> <div class="fw-bold text-dark small">{{ $item->subject_name }}</div>
@else @else
<span class="text-muted small"><i class="fa-solid fa-plus text-primary"></i> Add</span> <span class="text-muted small opacity-50"><i class="fa-solid fa-plus text-primary me-1"></i>Add</span>
@endif @endif
</div> </div>
@ -174,12 +207,12 @@
</div> </div>
</div> </div>
<!-- Modal for Edit / Update Slot --> <!-- Modal for Edit / Add Slot -->
<div class="modal fade" id="editSlotModal" tabindex="-1" aria-hidden="true"> <div class="modal fade" id="editSlotModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered"> <div class="modal-dialog modal-dialog-centered">
<div class="modal-content"> <div class="modal-content border-0 shadow">
<div class="modal-header bg-custom-header text-white"> <div class="modal-header bg-custom-header text-white">
<h5 class="modal-title"><i class="fa-solid fa-pen-to-square me-2"></i>Update Timetable Slot</h5> <h5 class="modal-title" id="modalTitle"><i class="fa-solid fa-pen-to-square me-2"></i>Update Timetable Slot</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button> <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div> </div>
<form action="{{ route('admin.timetable.store') }}" method="POST"> <form action="{{ route('admin.timetable.store') }}" method="POST">
@ -195,7 +228,7 @@
<div class="mb-3"> <div class="mb-3">
<label class="form-label fw-bold">Subject Name</label> <label class="form-label fw-bold">Subject Name</label>
<input type="text" name="subject_name" id="modal_subject" class="form-control" placeholder="e.g. Engine Repair" required> <input type="text" name="subject_name" id="modal_subject" class="form-control" placeholder="e.g. Engine Fundamentals" required>
</div> </div>
<div class="mb-3"> <div class="mb-3">
@ -215,7 +248,7 @@
</button> </button>
<div> <div>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-success"><i class="fa-solid fa-floppy-disk me-1"></i> Save / Update</button> <button type="submit" class="btn btn-success"><i class="fa-solid fa-floppy-disk me-1"></i> Save Changes</button>
</div> </div>
</div> </div>
</form> </form>
@ -241,11 +274,14 @@
currentSlotId = id; currentSlotId = id;
var clearBtn = document.getElementById('clearBtn'); var clearBtn = document.getElementById('clearBtn');
var modalTitle = document.getElementById('modalTitle');
if(id) { if(id) {
clearBtn.classList.remove('d-none'); clearBtn.classList.remove('d-none');
modalTitle.innerHTML = '<i class="fa-solid fa-pen-to-square me-2"></i>Edit Class Slot';
} else { } else {
clearBtn.classList.add('d-none'); clearBtn.classList.add('d-none');
modalTitle.innerHTML = '<i class="fa-solid fa-plus me-2"></i>Add Class Slot';
} }
} }

View File

@ -140,7 +140,7 @@ Route::middleware(['web'])->prefix('admin')->group(function () {
Route::get('/adminmycourses', [adminmycoursesController::class, 'index'])->name('admin.mycourses'); Route::get('/adminmycourses', [adminmycoursesController::class, 'index'])->name('admin.mycourses');
Route::post('/adminmycourses/store', [adminmycoursesController::class, 'store'])->name('admin.courses.store'); Route::post('/adminmycourses/store', [adminmycoursesController::class, 'store'])->name('admin.courses.store');
Route::post('/adminmycourses/update/{id}', [adminmycoursesController::class, 'update'])->name('admin.courses.update'); Route::post('/adminmycourses/update/{id}', [adminmycoursesController::class, 'update'])->name('admin.courses.update');
Route::delete('/adminmycourses/delete/{id}', [adminmycoursesController::class, 'destroy'])->name('admin.courses.delete'); Route::delete('/admin/courses/{id}', [adminmycoursesController::class, 'destroy'])->name('admin.courses.delete');
// Admin Timetable Routes // Admin Timetable Routes
Route::get('/timetable', [AdminTimetableController::class, 'index'])->name('admin.timetable'); Route::get('/timetable', [AdminTimetableController::class, 'index'])->name('admin.timetable');