Compare commits
45 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
e474bc5315 | |
|
|
8c953d0e46 | |
|
|
5a9580a568 | |
|
|
b3423db9d7 | |
|
|
876c896478 | |
|
|
3207bbddac | |
|
|
13ecc12812 | |
|
|
d6e1fe2c5d | |
|
|
97cf0f72d2 | |
|
|
6f1ef07048 | |
|
|
8d357652e7 | |
|
|
d7d4d815e3 | |
|
|
70a97b4019 | |
|
|
f4e4c45f5f | |
|
|
86a00cb09e | |
|
|
d3817ac619 | |
|
|
f5df67c87d | |
|
|
a3e71fd181 | |
|
|
c30d5a8d14 | |
|
|
cb50fbbb19 | |
|
|
e81d20fd50 | |
|
|
d71dc7ef62 | |
|
|
582c3a7e18 | |
|
|
523179880e | |
|
|
45fc7e33c9 | |
|
|
5f2abd44b4 | |
|
|
ba9b90f6e8 | |
|
|
e6b5166782 | |
|
|
db3373002d | |
|
|
d24235a2b7 | |
|
|
679e37b780 | |
|
|
41934b31fc | |
|
|
5d76c711f7 | |
|
|
705917497d | |
|
|
897cd82bc6 | |
|
|
d63e9c0a2b | |
|
|
fa299bcd7c | |
|
|
309934c18f | |
|
|
a03cfc0f40 | |
|
|
5ca81c9b24 | |
|
|
021ec03fda | |
|
|
2e799d798a | |
|
|
4289f1d576 | |
|
|
37cd68f170 | |
|
|
4f3a79c114 |
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class AdminAuthController extends Controller
|
||||
{
|
||||
|
||||
public function showLoginForm()
|
||||
{
|
||||
return view('adminlogin');
|
||||
}
|
||||
|
||||
|
||||
public function login(Request $request)
|
||||
{
|
||||
// 1. set Validation
|
||||
$request->validate([
|
||||
'username' => 'required',
|
||||
'password' => 'required',
|
||||
]);
|
||||
|
||||
|
||||
$admin = DB::table('adminlogins')->where('username', $request->username)->first();
|
||||
|
||||
|
||||
if ($admin && Hash::check($request->password, $admin->password)) {
|
||||
|
||||
|
||||
$request->session()->regenerate();
|
||||
|
||||
|
||||
session([
|
||||
'admin_id' => $admin->id,
|
||||
'admin_username' => $admin->username
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Login Successful!',
|
||||
'redirect_url' => route('admin.mycourses') // නැතහොත් route('admin.admindashboard')
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Wrong Username or Password!'
|
||||
], 401);
|
||||
}
|
||||
|
||||
|
||||
public function logout(Request $request)
|
||||
{
|
||||
|
||||
$request->session()->forget(['admin_id', 'admin_username']);
|
||||
$request->session()->invalidate();
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
|
||||
if ($request->ajax() || $request->wantsJson()) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'redirect_url' => route('admin.login')
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('admin.login')->with('success', 'Logged out successfully!');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\User;
|
||||
use App\Models\Notification;
|
||||
use App\Models\Timetable;
|
||||
use App\Models\StudentPortalLog;
|
||||
use Exception;
|
||||
|
||||
class AdminDashboardController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
try {
|
||||
// 1. Fetch Users
|
||||
$users = User::all();
|
||||
|
||||
// 2. Fetch Notifications
|
||||
$notifications = Notification::orderBy('created_at', 'desc')->get();
|
||||
$unreadNotifications = Notification::where('is_read', false)->count();
|
||||
|
||||
// 3. Fetch Timetable Slots Count
|
||||
$totalTimetableSlots = class_exists(Timetable::class) ? Timetable::count() : 0;
|
||||
|
||||
// 4. Fetch Portal Logs with user eager loaded
|
||||
$portalLogs = class_exists(StudentPortalLog::class)
|
||||
? StudentPortalLog::with('user')->get()
|
||||
: [];
|
||||
|
||||
return view('admin.AdminDashboard', compact(
|
||||
'users',
|
||||
'notifications',
|
||||
'unreadNotifications',
|
||||
'totalTimetableSlots',
|
||||
'portalLogs'
|
||||
));
|
||||
|
||||
} catch (Exception $e) {
|
||||
\Log::error('Admin Dashboard Error: ' . $e->getMessage());
|
||||
|
||||
if (config('app.debug')) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return back()->with('error', 'Something went wrong: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Notifications Store
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'title' => 'required|string|max:255',
|
||||
'message' => 'required|string',
|
||||
'type' => 'required|in:info,success,warning',
|
||||
]);
|
||||
|
||||
Notification::create([
|
||||
'title' => $request->title,
|
||||
'message' => $request->message,
|
||||
'type' => $request->type,
|
||||
'is_read' => false,
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Notification created successfully!');
|
||||
}
|
||||
|
||||
// Mark as Read
|
||||
public function markAsRead($id)
|
||||
{
|
||||
$notification = Notification::findOrFail($id);
|
||||
$notification->update(['is_read' => true]);
|
||||
|
||||
return redirect()->back()->with('success', 'Notification marked as read!');
|
||||
}
|
||||
|
||||
// Update Notification
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$request->validate([
|
||||
'title' => 'required|string|max:255',
|
||||
'message' => 'required|string',
|
||||
'type' => 'required|in:info,success,warning',
|
||||
]);
|
||||
|
||||
$notification = Notification::findOrFail($id);
|
||||
$notification->update($request->only(['title', 'message', 'type']));
|
||||
|
||||
return redirect()->back()->with('success', 'Notification updated successfully!');
|
||||
}
|
||||
|
||||
// Delete Notification
|
||||
public function destroy($id)
|
||||
{
|
||||
$notification = Notification::findOrFail($id);
|
||||
$notification->delete();
|
||||
|
||||
return redirect()->back()->with('success', 'Notification deleted successfully!');
|
||||
}
|
||||
|
||||
// Store Student Portal Log
|
||||
public function storePortalLog(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'user_id' => 'required|exists:users,id',
|
||||
]);
|
||||
|
||||
return $this->sendToPortalLog($request->user_id);
|
||||
}
|
||||
|
||||
// Send User to Portal Log
|
||||
public function sendToPortalLog($userId)
|
||||
{
|
||||
try
|
||||
{
|
||||
$user = User::findOrFail($userId);
|
||||
|
||||
|
||||
$exists = StudentPortalLog::where('user_id', $user->id)->exists();
|
||||
if ($exists) {
|
||||
return redirect()->back()->with('error', 'This user is already in Portal Logs!');
|
||||
}
|
||||
|
||||
|
||||
StudentPortalLog::create([
|
||||
'user_id' => $user->id,
|
||||
'first_name' => $user->first_name ?? '',
|
||||
'last_name' => $user->last_name ?? '',
|
||||
'email' => $user->email,
|
||||
'phone' => $user->phone ?? null,
|
||||
'pin' => null,
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'User successfully added to Portal Logs!');
|
||||
|
||||
}
|
||||
catch (Exception $e) {
|
||||
\Log::error('Send to Portal Log Error: ' . $e->getMessage());
|
||||
|
||||
return redirect()->back()->with('error', 'Failed to add user to Portal Log: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Update or Delete User Portal PIN
|
||||
public function updatePin(Request $request, $id)
|
||||
{
|
||||
$request->validate([
|
||||
'pin' => 'nullable|string|max:20',
|
||||
]);
|
||||
|
||||
try {
|
||||
$portalLog = StudentPortalLog::findOrFail($id);
|
||||
$portalLog->pin = $request->filled('pin') ? $request->pin : null;
|
||||
$portalLog->save();
|
||||
|
||||
$message = $request->filled('pin')
|
||||
? 'Portal PIN updated successfully!'
|
||||
: 'Portal PIN deleted successfully!';
|
||||
|
||||
return redirect()->back()->with('success', $message);
|
||||
|
||||
} catch (Exception $e) {
|
||||
\Log::error('Update PIN Error: ' . $e->getMessage());
|
||||
return redirect()->back()->with('error', 'Failed to update PIN: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// STUDENT PORTAL LOG DELETION ONLY
|
||||
// =========================================================================
|
||||
|
||||
|
||||
|
||||
public function destroyPortalLog($id)
|
||||
{
|
||||
try {
|
||||
$portalLog = StudentPortalLog::findOrFail($id);
|
||||
$portalLog->delete();
|
||||
|
||||
return redirect()->back()->with('success', 'Student Portal access record deleted successfully!');
|
||||
} catch (Exception $e) {
|
||||
\Log::error('Delete Portal Log Error: ' . $e->getMessage());
|
||||
return redirect()->back()->with('error', 'Failed to remove from Student Portal: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use App\Models\AdminLogin;
|
||||
|
||||
class AdminProfileController extends Controller
|
||||
{
|
||||
// Display Admin Profile
|
||||
public function index()
|
||||
{
|
||||
$adminId = session('admin_id');
|
||||
$admin = AdminLogin::find($adminId);
|
||||
|
||||
return view('admin.adminprofile', compact('admin'));
|
||||
}
|
||||
|
||||
// Update Username Information
|
||||
public function update(Request $request)
|
||||
{
|
||||
$adminId = session('admin_id');
|
||||
$admin = AdminLogin::findOrFail($adminId);
|
||||
|
||||
$request->validate([
|
||||
'username' => 'required|string|max:255|unique:adminlogins,username,' . $admin->id,
|
||||
]);
|
||||
|
||||
$admin->update([
|
||||
'username' => $request->username,
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Username updated successfully!');
|
||||
}
|
||||
|
||||
// Change Password
|
||||
public function updatePassword(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'current_password' => 'required',
|
||||
'new_password' => 'required|min:6|confirmed',
|
||||
]);
|
||||
|
||||
$adminId = session('admin_id');
|
||||
$admin = AdminLogin::findOrFail($adminId);
|
||||
|
||||
// Verify current password
|
||||
if (!Hash::check($request->current_password, $admin->password)) {
|
||||
return redirect()->back()->withErrors(['current_password' => 'Current password does not match our records.']);
|
||||
}
|
||||
|
||||
// Update to new password
|
||||
$admin->update([
|
||||
'password' => Hash::make($request->new_password)
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Password updated successfully!');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Result;
|
||||
use App\Imports\ResultsImport;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
|
||||
class AdminResultsController extends Controller
|
||||
{
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = Result::query();
|
||||
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$query->where(function ($q) use ($search) {
|
||||
$q->where('student_log_id', 'like', "%{$search}%")
|
||||
->orWhere('module_code', 'like', "%{$search}%")
|
||||
->orWhere('module_name', 'like', "%{$search}%");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if ($request->filled('academic_year')) {
|
||||
$query->where('academic_year', 'like', "%{$request->academic_year}%");
|
||||
}
|
||||
|
||||
|
||||
if ($request->filled('status')) {
|
||||
$query->where('status', $request->status);
|
||||
}
|
||||
|
||||
|
||||
$results = $query->orderBy('id', 'desc')->paginate(15)->withQueryString();
|
||||
|
||||
return view('admin.adminresults', compact('results'));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'student_log_id' => 'required|string|max:255',
|
||||
'module_code' => 'required|string|max:255',
|
||||
'module_name' => 'required|string|max:255',
|
||||
'academic_year' => 'required|string|max:255',
|
||||
'semester' => 'required|string|max:255',
|
||||
'marks' => 'required|numeric|min:0|max:100',
|
||||
'grade' => 'required|string|max:10',
|
||||
'status' => 'required|in:Pass,Fail',
|
||||
]);
|
||||
|
||||
Result::create($validated);
|
||||
|
||||
return redirect()->route('admin.results')->with('success', 'Exam result added successfully.');
|
||||
}
|
||||
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'student_log_id' => 'required|string|max:255',
|
||||
'module_code' => 'required|string|max:255',
|
||||
'module_name' => 'required|string|max:255',
|
||||
'academic_year' => 'required|string|max:255',
|
||||
'semester' => 'required|string|max:255',
|
||||
'marks' => 'required|numeric|min:0|max:100',
|
||||
'grade' => 'required|string|max:10',
|
||||
'status' => 'required|in:Pass,Fail',
|
||||
]);
|
||||
|
||||
$result = Result::findOrFail($id);
|
||||
$result->update($validated);
|
||||
|
||||
return redirect()->route('admin.results')->with('success', 'Exam result updated successfully.');
|
||||
}
|
||||
|
||||
public function destroy($id)
|
||||
{
|
||||
$result = Result::findOrFail($id);
|
||||
$result->delete();
|
||||
|
||||
return redirect()->route('admin.results')->with('success', 'Exam result deleted successfully.');
|
||||
}
|
||||
|
||||
public function import(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'excel_file' => 'required|mimes:xlsx,xls,csv|max:2048'
|
||||
]);
|
||||
|
||||
|
||||
Excel::import(new ResultsImport, $request->file('excel_file'));
|
||||
|
||||
|
||||
return redirect()->route('admin.results')->with('success', 'Excel file imported successfully!');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Timetable;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class AdminTimetableController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
if (!session()->has('admin_id')) {
|
||||
return redirect()->route('admin.login')->with('error', 'Please login first.');
|
||||
}
|
||||
|
||||
|
||||
$allTimetables = Timetable::all();
|
||||
|
||||
|
||||
$grid = [];
|
||||
foreach ($allTimetables as $item) {
|
||||
$grid[$item->time_slot][$item->day] = $item;
|
||||
}
|
||||
|
||||
$days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'];
|
||||
|
||||
|
||||
$timeSlots = [
|
||||
'08:30 - 10:30',
|
||||
'10:45 - 12:30',
|
||||
'12:30 - 01:30', // Lunch / Rest Time
|
||||
'01:30 - 03:30'
|
||||
];
|
||||
|
||||
// Today's Day Name
|
||||
$today = Carbon::now()->format('l');
|
||||
$todaySchedule = Timetable::where('day', $today)->get();
|
||||
|
||||
return view('admin.admintimetable', compact('allTimetables', 'days', 'timeSlots', 'grid', 'todaySchedule', 'today'));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'time_slot' => 'required|string',
|
||||
'day' => 'required|string',
|
||||
'subject_name' => 'required|string|max:255',
|
||||
'type' => 'required|string',
|
||||
]);
|
||||
|
||||
|
||||
Timetable::updateOrCreate(
|
||||
[
|
||||
'day' => $request->day,
|
||||
'time_slot' => $request->time_slot,
|
||||
],
|
||||
[
|
||||
'subject_name' => $request->subject_name,
|
||||
'type' => $request->type,
|
||||
]
|
||||
);
|
||||
|
||||
return redirect()->back()->with('success', 'Timetable saved successfully!');
|
||||
}
|
||||
|
||||
// Delete Single Slot
|
||||
public function destroy($id)
|
||||
{
|
||||
$timetable = Timetable::findOrFail($id);
|
||||
$timetable->delete();
|
||||
|
||||
return redirect()->back()->with('success', 'Timetable slot cleared successfully!');
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,8 @@ use Illuminate\Http\Request;
|
|||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use App\Mail\WelcomeMail;
|
||||
|
||||
class AuthController extends Controller
|
||||
{
|
||||
|
|
@ -18,6 +20,30 @@ class AuthController extends Controller
|
|||
}
|
||||
|
||||
|
||||
// public function register(Request $request)
|
||||
// {
|
||||
// $request->validate([
|
||||
// 'first_name' => 'required|string|max:255',
|
||||
// 'last_name' => 'required|string|max:255',
|
||||
// 'email' => 'required|string|email|max:255|unique:users',
|
||||
// 'phone' => 'required|string|max:15',
|
||||
// 'password' => 'required|string|min:8|confirmed',
|
||||
// ]);
|
||||
|
||||
// $user = User::create([
|
||||
// 'first_name' => $request->first_name,
|
||||
// 'last_name' => $request->last_name,
|
||||
// 'email' => $request->email,
|
||||
// 'phone' => $request->phone,
|
||||
// 'password' => Hash::make($request->password),
|
||||
// ]);
|
||||
|
||||
|
||||
// Auth::login($user);
|
||||
// return redirect('/')->with('success', 'Registration successful! Welcome to your dashboard.');
|
||||
// }
|
||||
|
||||
|
||||
public function register(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
|
|
@ -37,8 +63,14 @@ class AuthController extends Controller
|
|||
]);
|
||||
|
||||
|
||||
try {
|
||||
Mail::to($user->email)->send(new WelcomeMail($user));
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("Mail sending failed: " . $e->getMessage());
|
||||
}
|
||||
|
||||
Auth::login($user);
|
||||
return redirect('/')->with('success', 'Registration successful! Welcome to your dashboard.');
|
||||
return redirect()->route('signin')->with('success', 'Registration successful! Welcome to your dashboard.');
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class CoureseAssignController extends Controller
|
||||
{
|
||||
public function showMyCourse()
|
||||
{
|
||||
$studentLogId = session('student_log_id');
|
||||
$studentId = session('student_id');
|
||||
|
||||
if (!$studentLogId && !$studentId) {
|
||||
return redirect('/signin')->with('error', 'Please login first!');
|
||||
}
|
||||
|
||||
|
||||
$student = DB::table('student_details')
|
||||
->where('student_portal_log_id', $studentLogId)
|
||||
->orWhere('student_id', $studentId)
|
||||
->first();
|
||||
|
||||
if (!$student) {
|
||||
return redirect()->back()->with('error', 'Student record not found!');
|
||||
}
|
||||
|
||||
|
||||
$course = DB::table('courses')
|
||||
->join('course_assign_student', 'courses.id', '=', 'course_assign_student.course_id')
|
||||
->where('course_assign_student.student_details_id', $student->id)
|
||||
->select('courses.*')
|
||||
->first();
|
||||
|
||||
|
||||
return view('mycourse', compact('course', 'student'));
|
||||
}
|
||||
|
||||
public function showModule($id)
|
||||
{
|
||||
|
||||
return view('module', ['moduleId' => $id]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,333 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Dompdf\Dompdf;
|
||||
use Dompdf\Options;
|
||||
|
||||
class DocumentDownloadController extends Controller
|
||||
{
|
||||
/**
|
||||
* Check if student is authenticated via session or auth guard
|
||||
*/
|
||||
private function isAuthenticated(Request $request)
|
||||
{
|
||||
return $request->session()->has('student_id') ||
|
||||
$request->session()->has('student_log_id') ||
|
||||
auth()->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Academic Calendar PDF Download
|
||||
*/
|
||||
public function downloadAcademicCalendar(Request $request)
|
||||
{
|
||||
if (!$this->isAuthenticated($request)) {
|
||||
return redirect()->route('students')->with('error', 'Please login first to download official academic documents!');
|
||||
}
|
||||
|
||||
$title = "Official Academic Calendar 2026";
|
||||
$subtitle = "Semester Schedules, Lecture Weeks, Holidays & Important Deadlines";
|
||||
$refNo = "REF: AC-2026-CAL";
|
||||
|
||||
$tables = [
|
||||
[
|
||||
'title' => '1. SEMESTER DATES & LECTURE WEEKS',
|
||||
'headers' => ['Academic Event / Phase', 'Start Date', 'End Date', 'Status'],
|
||||
'rows' => [
|
||||
['Semester 1 Commencement', 'January 15, 2026', 'March 20, 2026', 'Active'],
|
||||
['Mid-Semester Recess', 'March 21, 2026', 'March 29, 2026', 'Scheduled'],
|
||||
['Practical Lab Intensive Weeks', 'March 30, 2026', 'May 15, 2026', 'Scheduled'],
|
||||
['Semester 1 Final Examinations', 'June 01, 2026', 'June 20, 2026', 'Scheduled'],
|
||||
['Semester 2 Commencement', 'July 15, 2026', 'November 30, 2026', 'Upcoming']
|
||||
]
|
||||
],
|
||||
[
|
||||
'title' => '2. INSTITUTIONAL & PUBLIC HOLIDAYS',
|
||||
'headers' => ['Holiday / Event Name', 'Date(s)', 'Impact on Classes'],
|
||||
'rows' => [
|
||||
['National Independence Day', 'February 04, 2026', 'Campus Closed'],
|
||||
['Sinhala & Tamil New Year Vacation', 'April 12 - April 18, 2026', 'No Lectures / Workshops'],
|
||||
['Vesak Festival Holiday', 'May 23 - May 25, 2026', 'Campus Closed'],
|
||||
['Annual Automotive Tech Symposium', 'August 20, 2026', 'Special Event (Mandatory Attendance)']
|
||||
]
|
||||
],
|
||||
[
|
||||
'title' => '3. CRITICAL ACADEMIC DEADLINES',
|
||||
'headers' => ['Deadline Description', 'Cut-off Date', 'Action Required'],
|
||||
'rows' => [
|
||||
['Course Module Drop / Add Period', 'February 10, 2026', 'Submit online form'],
|
||||
['Mid-Term Assignment 1 Submission', 'March 18, 2026', 'Upload via Portal'],
|
||||
['Examination Fee Clearance', 'May 15, 2026', 'Settle at Finance Office']
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
return $this->renderPdf($title, $subtitle, $refNo, $tables, "Academic_Calendar_2026.pdf");
|
||||
}
|
||||
|
||||
/**
|
||||
* Student Handbook PDF Download
|
||||
*/
|
||||
public function downloadStudentHandbook(Request $request)
|
||||
{
|
||||
if (!$this->isAuthenticated($request)) {
|
||||
return redirect()->route('students')->with('error', 'Please login first to download official academic documents!');
|
||||
}
|
||||
|
||||
$title = "Student Handbook & Code of Conduct";
|
||||
$subtitle = "Academic Regulations, Workshop Safety Rules & Grading Policies";
|
||||
$refNo = "REF: HB-2026-REG";
|
||||
|
||||
$tables = [
|
||||
[
|
||||
'title' => '1. ATTENDANCE & ACADEMIC INTEGRITY POLICIES',
|
||||
'headers' => ['Regulation Category', 'Requirement / Policy Detail', 'Penalty for Violation'],
|
||||
'rows' => [
|
||||
['Class Attendance', 'Minimum 80% attendance required for practical labs and lectures.', 'Barred from Final Exams'],
|
||||
['Academic Honesty', 'Zero tolerance for plagiarism, cheating, or proxy attendance.', 'Disciplinary Hearing & Grade F'],
|
||||
['Enrollment Status', 'Students must maintain continuous registration every term.', 'De-registration after 30 days']
|
||||
]
|
||||
],
|
||||
[
|
||||
'title' => '2. WORKSHOP & HIGH-VOLTAGE LAB SAFETY RULES',
|
||||
'headers' => ['Safety Protocol', 'Required Equipment / PPE', 'Compliance Rule'],
|
||||
'rows' => [
|
||||
['General Workshop PPE', 'Safety boots (steel toe), protective eyewear, lab coats', 'Mandatory at all times'],
|
||||
['Hybrid / EV High Voltage Labs', 'Class 0 rated insulated safety gloves (1000V rated)', 'Strict supervision required'],
|
||||
['Vehicle Lift Operation', 'Hydraulic lift locks must be verified before underbody work', 'Never operate alone']
|
||||
]
|
||||
],
|
||||
[
|
||||
'title' => '3. ACADEMIC GRADING SCHEME',
|
||||
'headers' => ['Grade', 'Percentage Range', 'GPA Value', 'Classification'],
|
||||
'rows' => [
|
||||
['A+', '90% - 100%', '4.00', 'High Distinction'],
|
||||
['A', '80% - 89%', '3.70', 'Distinction'],
|
||||
['B', '70% - 79%', '3.00', 'Credit Pass'],
|
||||
['C', '55% - 69%', '2.00', 'Pass'],
|
||||
['F', 'Below 50%', '0.00', 'Fail (Re-sit Required)']
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
return $this->renderPdf($title, $subtitle, $refNo, $tables, "Student_Handbook_2026.pdf");
|
||||
}
|
||||
|
||||
/**
|
||||
* Exam Code of Conduct PDF Download
|
||||
*/
|
||||
public function downloadExamCode(Request $request)
|
||||
{
|
||||
if (!$this->isAuthenticated($request)) {
|
||||
return redirect()->route('students')->with('error', 'Please login first to download official academic documents!');
|
||||
}
|
||||
|
||||
$title = "Exam Code of Conduct & Rules";
|
||||
$subtitle = "Examination Hall Admission, Practical Station Rules & Disciplinary Code";
|
||||
$refNo = "REF: EX-2026-RULES";
|
||||
|
||||
$tables = [
|
||||
[
|
||||
'title' => '1. EXAMINATION HALL ADMISSION RULES',
|
||||
'headers' => ['Rule Item', 'Requirement Detail', 'Enforcement'],
|
||||
'rows' => [
|
||||
['Student Identification', 'Valid Student ID Card & Exam Admission Ticket required.', 'Strictly Enforced'],
|
||||
['Entry Time Limit', 'Candidates admitted up to 30 minutes after commencement.', 'No extra time given'],
|
||||
['Prohibited Items', 'Mobile phones, smartwatches, programmable notes, bags.', 'Immediate Confiscation']
|
||||
]
|
||||
],
|
||||
[
|
||||
'title' => '2. PRACTICAL DIAGNOSTIC EXAMINATIONS',
|
||||
'headers' => ['Station Requirement', 'Procedure Standard', 'Evaluator Note'],
|
||||
'rows' => [
|
||||
['Station Attire', 'Clean workshop overall and non-slip safety shoes required.', 'Visual inspection at entry'],
|
||||
['Tool Calibration', 'Verify diagnostic scan tools before beginning fault-finding.', 'Instructor verification'],
|
||||
['Safety Shutoff', 'Always disengage high-voltage battery service plug first.', 'Immediate disqualification if missed']
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
return $this->renderPdf($title, $subtitle, $refNo, $tables, "Exam_Code_of_Conduct_2026.pdf");
|
||||
}
|
||||
|
||||
/**
|
||||
* Student Helpdesk Guide PDF Download
|
||||
*/
|
||||
public function downloadHelpdeskGuide(Request $request)
|
||||
{
|
||||
if (!$this->isAuthenticated($request)) {
|
||||
return redirect()->route('students')->with('error', 'Please login first to download official academic documents!');
|
||||
}
|
||||
|
||||
$title = "Student Helpdesk & Support Directory";
|
||||
$subtitle = "Portal Assistance, Technical Enquiries & Department Contact List";
|
||||
$refNo = "REF: HD-2026-SUPP";
|
||||
|
||||
$tables = [
|
||||
[
|
||||
'title' => '1. PORTAL & IT SUPPORT CHANNELS',
|
||||
'headers' => ['Support Issue', 'Resolution Method', 'Response Time'],
|
||||
'rows' => [
|
||||
['Password & PIN Reset', 'Self-service PIN reset or visit IT Help Desk (Level 2)', 'Instant / 15 Mins'],
|
||||
['Module Material Access', 'Email portal-support@autoedu.lk with Student ID', 'Within 2 Hours'],
|
||||
['Wi-Fi & Email Setup', 'Visit Student IT Counter with Student ID Card', 'Immediate']
|
||||
]
|
||||
],
|
||||
[
|
||||
'title' => '2. DEPARTMENT CONTACT DIRECTORY',
|
||||
'headers' => ['Department Name', 'Location', 'Extension', 'Official Email'],
|
||||
'rows' => [
|
||||
['Student Affairs & Registration', 'Admin Block - Ground Floor', 'Ext. 101', 'students@autoedu.lk'],
|
||||
['Finance & Tuition Payments', 'Admin Block - Room 104', 'Ext. 104', 'finance@autoedu.lk'],
|
||||
['Examinations & Results Branch', 'Academic Wing - Room 202', 'Ext. 108', 'exams@autoedu.lk'],
|
||||
['Automotive Workshop Office', 'Lab Complex - Block B', 'Ext. 112', 'workshop@autoedu.lk']
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
return $this->renderPdf($title, $subtitle, $refNo, $tables, "Student_Helpdesk_Support_Guide.pdf");
|
||||
}
|
||||
|
||||
/**
|
||||
* Render HTML to DomPDF output
|
||||
*/
|
||||
private function renderPdf($title, $subtitle, $refNo, $tables, $filename)
|
||||
{
|
||||
$studentName = session('student_name', 'Authenticated Student');
|
||||
$studentId = session('student_id', 'STU-2026-0042');
|
||||
$dateStr = date('F d, Y');
|
||||
|
||||
$tablesHtml = '';
|
||||
foreach ($tables as $table) {
|
||||
$tablesHtml .= '<div class="section-header">' . htmlspecialchars($table['title']) . '</div>';
|
||||
$tablesHtml .= '<table class="content-table"><thead><tr>';
|
||||
foreach ($table['headers'] as $th) {
|
||||
$tablesHtml .= '<th>' . htmlspecialchars($th) . '</th>';
|
||||
}
|
||||
$tablesHtml .= '</tr></thead><tbody>';
|
||||
foreach ($table['rows'] as $row) {
|
||||
$tablesHtml .= '<tr>';
|
||||
foreach ($row as $cell) {
|
||||
$tablesHtml .= '<td>' . htmlspecialchars($cell) . '</td>';
|
||||
}
|
||||
$tablesHtml .= '</tr>';
|
||||
}
|
||||
$tablesHtml .= 'tbody></table>';
|
||||
}
|
||||
|
||||
$html = '
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>' . htmlspecialchars($title) . '</title>
|
||||
<style>
|
||||
@page { margin: 25px 35px; }
|
||||
body { font-family: "Helvetica", "Arial", sans-serif; color: #1E293B; font-size: 11px; line-height: 1.5; }
|
||||
|
||||
.header-table { width: 100%; border-collapse: collapse; margin-bottom: 15px; border-bottom: 3px solid #3E51B8; padding-bottom: 10px; }
|
||||
.logo-title { font-size: 20px; font-weight: bold; color: #0F172A; text-transform: uppercase; letter-spacing: 0.5px; }
|
||||
.logo-sub { font-size: 10px; color: #64748B; margin-top: 3px; font-weight: normal; }
|
||||
.meta-badge { background: #0F172A; color: #FFE618; font-size: 9.5px; font-weight: bold; padding: 4px 10px; border-radius: 4px; display: inline-block; text-align: right; }
|
||||
|
||||
.doc-banner { background: #3E51B8; color: #ffffff; padding: 14px 18px; border-radius: 6px; margin-bottom: 18px; }
|
||||
.doc-banner h1 { margin: 0; font-size: 16px; font-weight: bold; text-transform: uppercase; }
|
||||
.doc-banner p { margin: 4px 0 0 0; font-size: 10.5px; color: #E2E8F0; }
|
||||
|
||||
.student-info-bar { background: #F8FAFC; border: 1px solid #E2E8F0; border-radius: 6px; padding: 8px 14px; margin-bottom: 18px; width: 100%; border-collapse: collapse; }
|
||||
.student-info-bar td { font-size: 10px; color: #334155; }
|
||||
.student-info-bar td strong { color: #0F172A; }
|
||||
|
||||
.section-header { background: #F1F5F9; border-left: 4px solid #BC1A1A; padding: 6px 10px; font-size: 11.5px; font-weight: bold; color: #0F172A; margin-top: 16px; margin-bottom: 8px; text-transform: uppercase; }
|
||||
|
||||
.content-table { width: 100%; border-collapse: collapse; margin-bottom: 14px; }
|
||||
.content-table th { background: #3E51B8; color: #ffffff; padding: 7px 10px; text-align: left; font-size: 10px; text-transform: uppercase; font-weight: bold; }
|
||||
.content-table td { padding: 7px 10px; border-bottom: 1px solid #E2E8F0; font-size: 10.5px; color: #334155; }
|
||||
.content-table tr:nth-child(even) td { background: #F8FAFC; }
|
||||
|
||||
.footer-box { margin-top: 25px; border-top: 1px solid #CBD5E1; padding-top: 10px; width: 100%; border-collapse: collapse; }
|
||||
.footer-box td { font-size: 9px; color: #64748B; }
|
||||
.stamp-box { border: 1.5px dashed #94A3B8; border-radius: 6px; padding: 8px; text-align: center; color: #475569; font-size: 8.5px; font-weight: bold; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Header -->
|
||||
<table class="header-table">
|
||||
<tr>
|
||||
<td>
|
||||
<div class="logo-title">AutoEdu Automotive Academy</div>
|
||||
<div class="logo-sub">Department of Automotive Engineering & Applied Research | ISO 9001 Certified</div>
|
||||
</td>
|
||||
<td style="text-align: right;">
|
||||
<div class="meta-badge">' . htmlspecialchars($refNo) . '</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- Document Banner -->
|
||||
<div class="doc-banner">
|
||||
<h1>' . htmlspecialchars($title) . '</h1>
|
||||
<p>' . htmlspecialchars($subtitle) . '</p>
|
||||
</div>
|
||||
|
||||
<!-- Student Info Bar -->
|
||||
<table class="student-info-bar">
|
||||
<tr>
|
||||
<td>Issued To: <strong>' . htmlspecialchars($studentName) . '</strong></td>
|
||||
<td>Student ID: <strong>' . htmlspecialchars($studentId) . '</strong></td>
|
||||
<td style="text-align: right;">Issue Date: <strong>' . htmlspecialchars($dateStr) . '</strong></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- Main Content Tables -->
|
||||
' . $tablesHtml . '
|
||||
|
||||
<!-- Footer -->
|
||||
<table class="footer-box">
|
||||
<tr>
|
||||
<td style="vertical-align: top;">
|
||||
<strong>AutoEdu Automotive Engineering Institute</strong><br>
|
||||
Main Campus, Academic Complex, Colombo, Sri Lanka<br>
|
||||
Hotline: +94 11 234 5678 | Email: support@autoedu.lk | Web: www.autoedu.lk<br>
|
||||
<em>Notice: This is an official computer-generated document verified for active student session.</em>
|
||||
</td>
|
||||
<td style="text-align: right; vertical-align: top; width: 150px;">
|
||||
<div class="stamp-box">
|
||||
<span style="color: #BC1A1A; font-weight: bold;">[ OFFICIAL SEAL ]</span><br>
|
||||
AUTHENTICATED DIGITAL COPY
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
';
|
||||
|
||||
try {
|
||||
$options = new Options();
|
||||
$options->set('isHtml5ParserEnabled', true);
|
||||
$options->set('isRemoteEnabled', true);
|
||||
|
||||
$dompdf = new Dompdf($options);
|
||||
$dompdf->loadHtml($html);
|
||||
$dompdf->setPaper('A4', 'portrait');
|
||||
$dompdf->render();
|
||||
|
||||
return response($dompdf->output(), 200, [
|
||||
'Content-Type' => 'application/pdf',
|
||||
'Content-Disposition' => 'attachment; filename="' . $filename . '"',
|
||||
'Cache-Control' => 'private, max-age=0, must-revalidate',
|
||||
'Pragma' => 'public'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
// Fallback response if rendering fails
|
||||
return response($html, 200, [
|
||||
'Content-Type' => 'text/html',
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,40 +3,75 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Feedback;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class FeedbackController extends Controller
|
||||
{
|
||||
// public function feedback(Request $request)
|
||||
// {
|
||||
|
||||
// $request->validate([
|
||||
// 'feedback_type' => 'required',
|
||||
// 'subject' => 'required|string|max:255',
|
||||
// 'feedback_text' => 'required|string',
|
||||
// ]);
|
||||
public function index(Request $request)
|
||||
{
|
||||
$studentLogId = session('student_log_id') ?? session('student_id');
|
||||
|
||||
if (!$studentLogId) {
|
||||
return redirect('/')->with('error', 'Please login first!');
|
||||
}
|
||||
|
||||
$feedbacks = DB::table('feedback')
|
||||
->where('student_id', $studentLogId)
|
||||
->orderBy('created_at', 'desc')
|
||||
->get();
|
||||
|
||||
return view('Feedback&Complain', compact('feedbacks'));
|
||||
}
|
||||
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$studentLogId = session('student_log_id') ?? session('student_id');
|
||||
|
||||
if (!$studentLogId) {
|
||||
return redirect('/')->with('error', 'Please login first to submit!');
|
||||
}
|
||||
|
||||
|
||||
$isComplaint = $request->has('is_complaint') && $request->is_complaint == "1";
|
||||
|
||||
if ($isComplaint) {
|
||||
|
||||
$request->validate([
|
||||
'complaint_category' => 'required',
|
||||
'complaint_title' => 'required|string|max:255',
|
||||
'complaint_details' => 'required|string',
|
||||
]);
|
||||
|
||||
$type = 'Complaint - ' . $request->complaint_category;
|
||||
$subject = $request->complaint_title;
|
||||
$text = $request->complaint_details;
|
||||
} else {
|
||||
|
||||
$request->validate([
|
||||
'feedback_type' => 'required',
|
||||
'subject' => 'required|string|max:255',
|
||||
'feedback_text' => 'required|string',
|
||||
]);
|
||||
|
||||
$type = 'Feedback - ' . $request->feedback_type;
|
||||
$subject = $request->subject;
|
||||
$text = $request->feedback_text;
|
||||
}
|
||||
|
||||
|
||||
DB::table('feedback')->insert([
|
||||
'student_id' => $studentLogId,
|
||||
'feedback_type' => $type,
|
||||
'subject' => $subject,
|
||||
'feedback_text' => $text,
|
||||
'status' => 'Pending',
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', ($isComplaint ? 'Complaint' : 'Feedback') . ' submitted successfully!');
|
||||
}
|
||||
|
||||
|
||||
// $studentLogId = session('student_portal_log_id');
|
||||
|
||||
|
||||
// if (!$studentLogId) {
|
||||
// return redirect('/')->with('error', 'Please login first to submit feedback!');
|
||||
// }
|
||||
|
||||
|
||||
// DB::table('feedbacks')->insert([
|
||||
// 'student_id' => $studentLogId,
|
||||
// 'feedback_type' => $request->feedback_type,
|
||||
// 'subject' => $request->subject,
|
||||
// 'feedback_text' => $request->feedback_text,
|
||||
// 'status' => 'Pending',
|
||||
// 'created_at' => now(),
|
||||
// 'updated_at' => now(),
|
||||
// ]);
|
||||
|
||||
|
||||
// return redirect()->back()->with('success', 'Feedback submitted successfully!');
|
||||
// }
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Collection;
|
||||
use App\Models\courses;
|
||||
use App\Models\Module;
|
||||
use App\Models\StudentDetail;
|
||||
use App\Models\CourseAssignStudent;
|
||||
|
||||
|
||||
class MyCoursesController extends Controller
|
||||
{
|
||||
public function showMyCourses()
|
||||
{
|
||||
$userId = session('student_portal_log_id')
|
||||
?? session('student_id')
|
||||
?? session('id')
|
||||
?? Auth::id();
|
||||
|
||||
$student = DB::table('student_details')
|
||||
->where('student_portal_log_id', $userId)
|
||||
->orWhere('id', $userId)
|
||||
->orWhere('student_id', $userId)
|
||||
->first();
|
||||
|
||||
if (!$student) {
|
||||
return view('mycourse', [
|
||||
'courses' => collect([]),
|
||||
'student' => null
|
||||
]);
|
||||
}
|
||||
|
||||
// DB::table භාවිතයෙන් SQL join එක නිවැරදිව සිදු කිරීම
|
||||
$courses = DB::table('courses')
|
||||
->join('course_assign_student', 'courses.id', '=', 'course_assign_student.course_id')
|
||||
->leftJoin('modules', 'courses.id', '=', 'modules.course_id') // <-- මේ පේළිය එකතු කරන ලදී
|
||||
->whereIn('course_assign_student.student_id', array_filter([
|
||||
$student->id ?? null,
|
||||
$student->student_id ?? null,
|
||||
$student->student_portal_log_id ?? null
|
||||
]))
|
||||
->select(
|
||||
'courses.id as course_id',
|
||||
'courses.title as course_title',
|
||||
'courses.course_code',
|
||||
'modules.id as module_id',
|
||||
'modules.title as module_title',
|
||||
'modules.description as module_description',
|
||||
'modules.semester'
|
||||
)
|
||||
->get()
|
||||
->groupBy('course_id');
|
||||
|
||||
return view('mycourse', compact('courses', 'student'));
|
||||
}
|
||||
|
||||
// public function showModule($course_id)
|
||||
// {
|
||||
// $course = DB::table('courses')->where('id', $course_id)->first();
|
||||
|
||||
// if (!$course) {
|
||||
// abort(404, 'Course not found');
|
||||
// }
|
||||
|
||||
// $modules = DB::table('modules')
|
||||
// ->where('course_id', $course_id)
|
||||
// ->get();
|
||||
|
||||
// return view('module', compact('course', 'modules'));
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Result;
|
||||
|
||||
class ResultsController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
|
||||
$studentLogId = session('student_log_id') ?? session('student_id');
|
||||
|
||||
|
||||
if (!$studentLogId) {
|
||||
return redirect('/signin')->with('error', 'Please login first!');
|
||||
}
|
||||
|
||||
|
||||
$results = Result::where('student_log_id', $studentLogId)->get();
|
||||
|
||||
|
||||
$totalModules = $results->count();
|
||||
|
||||
$passedModules = $results->filter(function ($item) {
|
||||
return strtolower(trim($item->status)) === 'pass';
|
||||
})->count();
|
||||
|
||||
$averageMarks = $totalModules > 0 ? round($results->avg('marks'), 1) : 0;
|
||||
|
||||
|
||||
return view('results', compact('results', 'totalModules', 'passedModules', 'averageMarks'));
|
||||
}
|
||||
}
|
||||
|
|
@ -4,58 +4,234 @@ namespace App\Http\Controllers;
|
|||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Models\StudentPortalLog ;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
|
||||
use App\Models\Notification;
|
||||
|
||||
class StudentPortalController extends Controller
|
||||
{public function index(Request $request)
|
||||
{
|
||||
|
||||
if (!session()->has('student_id') && !session()->has('student_log_id')) {
|
||||
return redirect('/signin')->with('error', 'Please login first!');
|
||||
}
|
||||
|
||||
|
||||
$notifications = Notification::latest()->take(10)->get();
|
||||
$unreadNotifications = Notification::where('is_read', 0)->count();
|
||||
|
||||
|
||||
return view('StudentPortal', compact('notifications', 'unreadNotifications'));
|
||||
}
|
||||
|
||||
public function studentlogin(Request $request)
|
||||
{
|
||||
|
||||
$request->validate([
|
||||
'username' => 'required',
|
||||
'password' => 'required',
|
||||
'username' => 'required|string',
|
||||
'password' => 'required|string',
|
||||
'pin' => 'required|numeric',
|
||||
]);
|
||||
|
||||
|
||||
$student = DB::table('student_portal_logs')
|
||||
->where('email', $request->username)
|
||||
->orWhere('studentid', $request->username)
|
||||
->first();
|
||||
|
||||
|
||||
if ($student && Hash::check($request->password, $student->password) && $student->pin == $request->pin) {
|
||||
if ($student->status !== 'active' && $student->status !== '') {
|
||||
return redirect('/')->with('error', 'Your account is inactive!');
|
||||
|
||||
if ($student->status !== 'active' && $student->status !== '' && !is_null($student->status)) {
|
||||
return redirect()->back()->with('error', 'Your account is inactive!');
|
||||
}
|
||||
|
||||
|
||||
$request->session()->put('student_id', $student->studentid);
|
||||
$request->session()->put('student_log_id', $student->id ?? null);
|
||||
|
||||
$name = trim(($student->first_name ?? '') . ' ' . ($student->last_name ?? ''));
|
||||
$request->session()->put('student_name', $name ?: ($student->email ?? $student->studentid));
|
||||
|
||||
return redirect()->route('student.portal')->with('success', 'Logged in successfully!');
|
||||
}
|
||||
return redirect('/')->with('error', 'Invalid Email, Password, or PIN!');
|
||||
|
||||
return redirect()->back()->with('error', 'Invalid Email/Username, Password, or PIN!');
|
||||
}
|
||||
|
||||
public function showProfile(Request $request)
|
||||
{
|
||||
|
||||
$log_id = $request->session()->get('student_log_id');
|
||||
$student_code = $request->session()->get('student_id');
|
||||
|
||||
if (!$log_id && !$student_code) {
|
||||
return redirect('/')->with('error', 'Please login first!');
|
||||
}
|
||||
|
||||
|
||||
// public function showProfile(Request $request)
|
||||
// {
|
||||
|
||||
// $log_id = $request->session()->get('student_id');
|
||||
|
||||
|
||||
// if (!$log_id) {
|
||||
// return redirect('/')->with('error', 'Please login first!');
|
||||
// }
|
||||
|
||||
|
||||
// $student = DB::table('student_details')
|
||||
// ->where('student_portal_log_id', $log_id)
|
||||
// ->first();
|
||||
|
||||
|
||||
// if (!$student) {
|
||||
// return redirect()->back()->with('error', 'Student details not found!');
|
||||
// }
|
||||
|
||||
|
||||
// return view('StudentProfile', compact('student'));
|
||||
// }
|
||||
|
||||
$student = DB::table('student_details')
|
||||
->where(function ($query) use ($log_id, $student_code) {
|
||||
if ($log_id) {
|
||||
$query->where('student_portal_log_id', $log_id);
|
||||
}
|
||||
if ($student_code) {
|
||||
|
||||
if ($log_id) {
|
||||
$query->orWhere('student_id', $student_code);
|
||||
} else {
|
||||
$query->where('student_id', $student_code);
|
||||
}
|
||||
}
|
||||
})
|
||||
->first();
|
||||
|
||||
|
||||
if (!$student) {
|
||||
return redirect()->route('student.portal')->with('error', 'Student details not found in database!');
|
||||
}
|
||||
|
||||
|
||||
return view('StudentProfile', compact('student'));
|
||||
}
|
||||
|
||||
public function updateProfile(Request $request)
|
||||
{
|
||||
$log_id = $request->session()->get('student_log_id');
|
||||
$student_code = $request->session()->get('student_id');
|
||||
|
||||
if (!$log_id && !$student_code) {
|
||||
return redirect('/')->with('error', 'Please login first!');
|
||||
}
|
||||
|
||||
$request->validate([
|
||||
'full_name' => 'required|string|max:255',
|
||||
'nic_passport' => 'nullable|string|max:100',
|
||||
'date_of_birth' => 'nullable|date',
|
||||
'gender' => 'nullable|string|max:20',
|
||||
'email' => 'required|email|max:255',
|
||||
'phone' => 'nullable|string|max:50',
|
||||
'qualification' => 'nullable|string|max:255',
|
||||
'institute' => 'nullable|string|max:255',
|
||||
'year_completed' => 'nullable|string|max:50',
|
||||
'profile_image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:5120',
|
||||
]);
|
||||
|
||||
$student = DB::table('student_details')
|
||||
->where(function ($query) use ($log_id, $student_code) {
|
||||
if ($log_id) {
|
||||
$query->where('student_portal_log_id', $log_id);
|
||||
}
|
||||
if ($student_code) {
|
||||
if ($log_id) {
|
||||
$query->orWhere('student_id', $student_code);
|
||||
} else {
|
||||
$query->where('student_id', $student_code);
|
||||
}
|
||||
}
|
||||
})
|
||||
->first();
|
||||
|
||||
if (!$student) {
|
||||
return redirect()->back()->with('error', 'Student profile record not found!');
|
||||
}
|
||||
|
||||
$updateData = [
|
||||
'full_name' => $request->full_name,
|
||||
'nic_passport' => $request->nic_passport,
|
||||
'date_of_birth' => $request->date_of_birth,
|
||||
'gender' => $request->gender,
|
||||
'email' => $request->email,
|
||||
'phone' => $request->phone,
|
||||
'qualification' => $request->qualification,
|
||||
'institute' => $request->institute,
|
||||
'year_completed' => $request->year_completed,
|
||||
'updated_at' => now(),
|
||||
];
|
||||
|
||||
// 1. Check if user requested to REMOVE image
|
||||
if ($request->input('remove_profile_image') == '1') {
|
||||
if (!empty($student->image) && file_exists(public_path($student->image))) {
|
||||
@unlink(public_path($student->image));
|
||||
}
|
||||
$updateData['image'] = null;
|
||||
}
|
||||
// 2. Check if user provided CROPPED Base64 image
|
||||
elseif (!empty($request->input('cropped_image_data'))) {
|
||||
$base64Image = $request->input('cropped_image_data');
|
||||
if (preg_match('/^data:image\/(\w+);base64,/', $base64Image, $type)) {
|
||||
$data = substr($base64Image, strpos($base64Image, ',') + 1);
|
||||
$type = strtolower($type[1]);
|
||||
if (in_array($type, ['jpg', 'jpeg', 'gif', 'png'])) {
|
||||
$data = base64_decode($data);
|
||||
if ($data !== false) {
|
||||
$filename = time() . '_' . uniqid() . '.png';
|
||||
$destinationPath = public_path('uploads/student_images');
|
||||
if (!file_exists($destinationPath)) {
|
||||
mkdir($destinationPath, 0777, true);
|
||||
}
|
||||
file_put_contents($destinationPath . '/' . $filename, $data);
|
||||
|
||||
// Delete old image if existed
|
||||
if (!empty($student->image) && file_exists(public_path($student->image))) {
|
||||
@unlink(public_path($student->image));
|
||||
}
|
||||
|
||||
$updateData['image'] = 'uploads/student_images/' . $filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 3. Fallback to normal direct file upload
|
||||
elseif ($request->hasFile('profile_image')) {
|
||||
$file = $request->file('profile_image');
|
||||
$filename = time() . '_' . uniqid() . '.' . $file->getClientOriginalExtension();
|
||||
$destinationPath = public_path('uploads/student_images');
|
||||
if (!file_exists($destinationPath)) {
|
||||
mkdir($destinationPath, 0777, true);
|
||||
}
|
||||
$file->move($destinationPath, $filename);
|
||||
|
||||
if (!empty($student->image) && file_exists(public_path($student->image))) {
|
||||
@unlink(public_path($student->image));
|
||||
}
|
||||
|
||||
$updateData['image'] = 'uploads/student_images/' . $filename;
|
||||
}
|
||||
|
||||
DB::table('student_details')
|
||||
->where('id', $student->id)
|
||||
->update($updateData);
|
||||
|
||||
if (!empty($student->student_portal_log_id)) {
|
||||
DB::table('student_portal_logs')
|
||||
->where('id', $student->student_portal_log_id)
|
||||
->update([
|
||||
'email' => $request->email,
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
$request->session()->put('student_name', $request->full_name);
|
||||
$request->session()->put('student_email', $request->email);
|
||||
|
||||
return redirect()->back()->with('success', 'Profile updated successfully!');
|
||||
}
|
||||
|
||||
public function studentlogout(Request $request)
|
||||
{
|
||||
|
||||
$request->session()->forget(['student_id', 'student_log_id', 'student_name', 'student_email']);
|
||||
$request->session()->invalidate();
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
|
||||
if ($request->wantsJson() || $request->ajax()) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Logged out successfully!'
|
||||
], 200);
|
||||
}
|
||||
|
||||
return redirect('/')->with('success', 'Logged out successfully!');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Timetable;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class TimetableController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$studentLogId = session('student_log_id') ?? session('student_id');
|
||||
|
||||
if (!$studentLogId) {
|
||||
return redirect('/signin')->with('error', 'Please login first!');
|
||||
}
|
||||
|
||||
|
||||
$rawTimetables = Timetable::all();
|
||||
|
||||
$schedule = [];
|
||||
$timeSlots = [];
|
||||
|
||||
foreach ($rawTimetables as $item) {
|
||||
if (!in_array($item->time_slot, $timeSlots)) {
|
||||
$timeSlots[] = $item->time_slot;
|
||||
}
|
||||
$schedule[$item->time_slot][$item->day] = $item;
|
||||
}
|
||||
|
||||
|
||||
$todayName = Carbon::now()->format('l');
|
||||
$todaySchedule = Timetable::where('day', $todayName)
|
||||
->where('type', '!=', 'Break')
|
||||
->get();
|
||||
|
||||
$days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'];
|
||||
|
||||
return view('timetable', compact('schedule', 'timeSlots', 'days', 'todaySchedule', 'todayName'));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Models\CourseAssignStudent;
|
||||
use App\Models\Course;
|
||||
use App\Models\studentDetails;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class adminmycoursesController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
if (!session()->has('admin_id')) {
|
||||
return redirect('/admin/login')->with('error', 'Please login first!');
|
||||
}
|
||||
|
||||
// Fetch courses and manually attach modules to each course object
|
||||
$courses = DB::table('courses')->orderBy('id', 'desc')->get();
|
||||
|
||||
foreach ($courses as $course) {
|
||||
$course->modules = DB::table('course_modules')
|
||||
->where('course_id', $course->id)
|
||||
->orderBy('semester', 'asc')
|
||||
->orderBy('id', 'asc')
|
||||
->get();
|
||||
}
|
||||
|
||||
// Needed for the "Assign Course to Students" modal on this page
|
||||
$students = studentDetails::all();
|
||||
|
||||
return view('admin.adminmycourses', compact('courses', 'students'));
|
||||
}
|
||||
|
||||
// --- COURSE CRUD METHODS ---
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'title' => 'required|string|max:255',
|
||||
'course_code' => 'required|string|max:50',
|
||||
'image' => 'nullable|image|mimes:jpeg,png,jpg,gif,webp|max:2048',
|
||||
'duration' => 'required|string',
|
||||
'level' => 'required|string',
|
||||
'author' => 'nullable|string',
|
||||
'desc' => 'nullable|string',
|
||||
'status' => 'required|string',
|
||||
]);
|
||||
|
||||
$imagePath = null;
|
||||
if ($request->hasFile('image')) {
|
||||
$imagePath = $request->file('image')->store('courses', 'public');
|
||||
}
|
||||
|
||||
DB::table('courses')->insert([
|
||||
'title' => $request->title,
|
||||
'course_code' => $request->course_code,
|
||||
'image' => $imagePath,
|
||||
'duration' => $request->duration,
|
||||
'level' => $request->level,
|
||||
'author' => $request->author ?? 'Admin',
|
||||
'desc' => $request->desc,
|
||||
'student' => $request->student ?? 0,
|
||||
'rating' => $request->rating ?? 0.0,
|
||||
'badge' => $request->badge,
|
||||
'trending' => $request->has('trending') ? 1 : 0,
|
||||
'status' => $request->status,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Course added successfully!');
|
||||
}
|
||||
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$request->validate([
|
||||
'title' => 'required|string|max:255',
|
||||
'course_code' => 'required|string|max:50',
|
||||
'image' => 'nullable|image|mimes:jpeg,png,jpg,gif,webp|max:2048',
|
||||
'duration' => 'required|string',
|
||||
'level' => 'required|string',
|
||||
'status' => 'required|string',
|
||||
]);
|
||||
|
||||
$course = DB::table('courses')->where('id', $id)->first();
|
||||
|
||||
if (!$course) {
|
||||
return redirect()->back()->with('error', 'Course not found!');
|
||||
}
|
||||
|
||||
$imagePath = $course->image;
|
||||
if ($request->hasFile('image')) {
|
||||
if ($course->image && Storage::disk('public')->exists($course->image)) {
|
||||
Storage::disk('public')->delete($course->image);
|
||||
}
|
||||
$imagePath = $request->file('image')->store('courses', 'public');
|
||||
}
|
||||
|
||||
DB::table('courses')->where('id', $id)->update([
|
||||
'title' => $request->title,
|
||||
'course_code' => $request->course_code,
|
||||
'image' => $imagePath,
|
||||
'duration' => $request->duration,
|
||||
'level' => $request->level,
|
||||
'author' => $request->author ?? $course->author ?? 'Admin',
|
||||
'desc' => $request->desc ?? $request->description ?? $course->desc,
|
||||
'badge' => $request->badge ?? $course->badge,
|
||||
'trending' => $request->has('trending') ? 1 : 0,
|
||||
'status' => $request->status,
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Course updated successfully!');
|
||||
}
|
||||
|
||||
public function destroy($id)
|
||||
{
|
||||
$course = DB::table('courses')->where('id', $id)->first();
|
||||
|
||||
if ($course) {
|
||||
if ($course->image && Storage::disk('public')->exists($course->image)) {
|
||||
Storage::disk('public')->delete($course->image);
|
||||
}
|
||||
|
||||
// Clean up related modules
|
||||
DB::table('course_modules')->where('course_id', $id)->delete();
|
||||
DB::table('courses')->where('id', $id)->delete();
|
||||
|
||||
return redirect()->back()->with('success', 'Course deleted successfully!');
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', 'Course not found!');
|
||||
}
|
||||
|
||||
// --- MODULE CRUD METHODS ---
|
||||
|
||||
public function storeModule(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'course_id' => 'required',
|
||||
'module_code' => 'required|string|max:50',
|
||||
'title' => 'required|string|max:255',
|
||||
'semester' => 'required|string',
|
||||
'credits' => 'nullable|integer',
|
||||
'description' => 'nullable|string',
|
||||
]);
|
||||
|
||||
DB::table('course_modules')->insert([
|
||||
'course_id' => $request->course_id,
|
||||
'module_code' => $request->module_code,
|
||||
'title' => $request->title,
|
||||
'semester' => $request->semester,
|
||||
'credits' => $request->credits,
|
||||
'description' => $request->description,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Module added successfully!');
|
||||
}
|
||||
|
||||
public function updateModule(Request $request, $id)
|
||||
{
|
||||
$request->validate([
|
||||
'module_code' => 'required|string|max:50',
|
||||
'title' => 'required|string|max:255',
|
||||
'semester' => 'required|string',
|
||||
'credits' => 'nullable|integer',
|
||||
'description' => 'nullable|string',
|
||||
]);
|
||||
|
||||
DB::table('course_modules')->where('id', $id)->update([
|
||||
'module_code' => $request->module_code,
|
||||
'title' => $request->title,
|
||||
'semester' => $request->semester,
|
||||
'credits' => $request->credits,
|
||||
'description' => $request->description,
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
return redirect()->back()->with('success', 'Module updated successfully!');
|
||||
}
|
||||
|
||||
public function destroyModule($id)
|
||||
{
|
||||
DB::table('course_modules')->where('id', $id)->delete();
|
||||
return redirect()->back()->with('success', 'Module deleted successfully!');
|
||||
}
|
||||
|
||||
// --- ASSIGN COURSE TO STUDENTS ---
|
||||
|
||||
/**
|
||||
* Handles the POST from the "Assign Course to Students" modal.
|
||||
* Route name: assign.course
|
||||
*/
|
||||
public function assignCourse(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'course_id' => 'required|exists:courses,id',
|
||||
'student_ids' => 'required|array|min:1',
|
||||
'student_ids.*' => 'exists:student_details,id',
|
||||
]);
|
||||
|
||||
foreach ($request->student_ids as $studentId) {
|
||||
|
||||
CourseAssignStudent::updateOrCreate(
|
||||
[
|
||||
'course_id' => $request->course_id,
|
||||
'student_id' => $studentId,
|
||||
]
|
||||
);
|
||||
// CourseAssignStudent::updateOrCreate(
|
||||
// [
|
||||
// 'course_id' => $request->course_id,
|
||||
// 'student_id' => $studentId,
|
||||
// ],
|
||||
// [
|
||||
// 'assigned_at' => now(),
|
||||
// ]
|
||||
// );
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', 'Course assigned to selected students successfully!');
|
||||
}
|
||||
}
|
||||
|
||||
Schema::getColumnListing('course_assign_student');
|
||||
|
|
@ -2,9 +2,60 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Application;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class applyController extends Controller
|
||||
class ApplyController extends Controller
|
||||
{
|
||||
//
|
||||
public function index()
|
||||
{
|
||||
return view('apply');
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
|
||||
$validatedData = $request->validate([
|
||||
'first_name' => 'required|string|max:255',
|
||||
'last_name' => 'required|string|max:255',
|
||||
'nic' => 'nullable|string|max:50',
|
||||
'nationality' => 'nullable|string|max:100',
|
||||
'address' => 'required|string|max:500',
|
||||
'state' => 'required|string|max:255',
|
||||
'gender' => 'nullable|string',
|
||||
'dob' => 'nullable|date',
|
||||
'mobile' => 'required|string|max:20',
|
||||
'mobile2' => 'nullable|string|max:20',
|
||||
'email' => 'required|email|max:255',
|
||||
'preferred_contact_method' => 'nullable|string',
|
||||
'still_at_school' => 'nullable|string',
|
||||
'highest_qualification' => 'nullable|string',
|
||||
'school_name' => 'nullable|string|max:255',
|
||||
'year_completed' => 'nullable|numeric|digits:4',
|
||||
'exam_passed' => 'nullable|string',
|
||||
'subjects' => 'nullable|string|max:255',
|
||||
'grades_results' => 'nullable|string',
|
||||
'certificates.*' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:5120', // Max 5MB per file
|
||||
'emergency_contact_name' => 'required|string|max:255',
|
||||
'emergency_contact_relationship' => 'required|string|max:255',
|
||||
]);
|
||||
|
||||
|
||||
$certificatePaths = [];
|
||||
if ($request->hasFile('certificates')) {
|
||||
foreach ($request->file('certificates') as $file) {
|
||||
$path = $file->store('certificates', 'public');
|
||||
$certificatePaths[] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$application = new Application($validatedData);
|
||||
$application->user_id = Auth::id();
|
||||
$application->certificates = $certificatePaths;
|
||||
$application->save();
|
||||
|
||||
return redirect()->back()->with('success', 'Your application has been submitted successfully!');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use App\Mail\OtpEmail;
|
||||
use App\Models\User;
|
||||
|
||||
class ForgotPasswordController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return view('forgotPassword');
|
||||
}
|
||||
|
||||
public function resetEmail(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'email' => 'required|email|exists:users,email'
|
||||
], [
|
||||
'email.exists' => 'The provided email is not registered in our system.'
|
||||
]);
|
||||
|
||||
$email = $request->input('email');
|
||||
$user = User::where('email', $email)->first();
|
||||
|
||||
$otp = random_int(100000, 999999);
|
||||
|
||||
Session::put('otp', $otp);
|
||||
Session::put('email', $email);
|
||||
|
||||
$user->email_otp = $otp;
|
||||
$user->save();
|
||||
|
||||
Mail::to($email)->send(new OtpEmail($otp));
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'OTP has been sent to your email.'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function verifyOtpEmail(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'otp' => 'required|numeric'
|
||||
]);
|
||||
|
||||
$otp = $request->input('otp');
|
||||
$email = Session::get('email');
|
||||
|
||||
if (!$email) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Session expired. Please request a new OTP.'
|
||||
], 400);
|
||||
}
|
||||
|
||||
$user = User::where('email', $email)
|
||||
->where('email_otp', $otp)
|
||||
->first();
|
||||
|
||||
if ($user) {
|
||||
Session::put('otp_verified', true);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'OTP is correct.',
|
||||
'email' => $email
|
||||
]);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Invalid OTP code. Please try again.'
|
||||
], 422);
|
||||
}
|
||||
|
||||
public function updatePassword(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'email' => 'required|email|exists:users,email',
|
||||
'password_mo' => 'required|string|min:8|confirmed',
|
||||
]);
|
||||
|
||||
$email = $request->input('email');
|
||||
|
||||
if (!Session::get('otp_verified') || Session::get('email') !== $email) {
|
||||
return redirect()->back()->with('error', 'Unauthorized access or session expired.');
|
||||
}
|
||||
|
||||
$user = User::where('email', $email)->first();
|
||||
|
||||
if ($user) {
|
||||
$user->password = Hash::make($request->input('password_mo'));
|
||||
$user->email_otp = null;
|
||||
$user->save();
|
||||
|
||||
Session::forget(['otp', 'email', 'otp_verified']);
|
||||
|
||||
return redirect('/signin')->with('success', 'Password updated successfully. Please login.');
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', 'User not found.');
|
||||
}
|
||||
}
|
||||
|
|
@ -2,9 +2,16 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\courses;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class coursesController extends Controller
|
||||
{
|
||||
//
|
||||
public function index()
|
||||
{
|
||||
|
||||
$courses = courses::all();
|
||||
|
||||
return view('courses', compact('courses'));
|
||||
}
|
||||
}
|
||||
|
|
@ -3,14 +3,18 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class studentportalnavController extends Controller
|
||||
{
|
||||
public function logout(Request $request)
|
||||
{
|
||||
|
||||
$request->session()->forget(['student_log_id', 'student_id']);
|
||||
Auth::logout();
|
||||
$request->session()->invalidate();
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Logged out successfully'
|
||||
|
|
|
|||
|
|
@ -1,10 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\courses;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class welcomeController extends Controller
|
||||
{
|
||||
//
|
||||
|
||||
public function index()
|
||||
{
|
||||
|
||||
$courses = courses::where('status', 'active')
|
||||
->latest()
|
||||
->take(3)
|
||||
->get();
|
||||
|
||||
return view('welcome', compact('courses'));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace App\Imports;
|
||||
|
||||
use App\Models\Result;
|
||||
use Maatwebsite\Excel\Concerns\ToModel;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadingRow;
|
||||
|
||||
class ResultsImport implements ToModel, WithHeadingRow
|
||||
{
|
||||
public function model(array $row)
|
||||
{
|
||||
return new Result([
|
||||
'student_log_id' => $row['student_log_id'],
|
||||
'module_code' => $row['module_code'],
|
||||
'module_name' => $row['module_name'],
|
||||
'academic_year' => $row['academic_year'],
|
||||
'semester' => $row['semester'],
|
||||
'marks' => $row['marks'],
|
||||
'grade' => $row['grade'],
|
||||
'status' => $row['status'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Attachment;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class OtpEmail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public $otp;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct($otp)
|
||||
{
|
||||
$this->otp = $otp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*/
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
return new Envelope(
|
||||
subject: 'Academy - Password Reset OTP',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*/
|
||||
public function content(): Content
|
||||
{
|
||||
return new Content(
|
||||
view: 'Mail.otp',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachments for the message.
|
||||
*
|
||||
* @return array<int, Attachment>
|
||||
*/
|
||||
public function attachments(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\User; // 1. User Model එක Import කළා
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Attachment;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class WelcomeMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*/
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
return new Envelope(
|
||||
subject: 'Welcome to Student Registration!', // Email එකේ Subject එක
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*/
|
||||
public function content(): Content
|
||||
{
|
||||
return new Content(
|
||||
view: 'mail.welcome',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachments for the message.
|
||||
*
|
||||
* @return array<int, Attachment>
|
||||
*/
|
||||
public function attachments(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Application extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'nic',
|
||||
'nationality',
|
||||
'address',
|
||||
'state',
|
||||
'gender',
|
||||
'dob',
|
||||
'mobile',
|
||||
'mobile2',
|
||||
'email',
|
||||
'preferred_contact_method',
|
||||
'still_at_school',
|
||||
'highest_qualification',
|
||||
'school_name',
|
||||
'year_completed',
|
||||
'exam_passed',
|
||||
'subjects',
|
||||
'grades_results',
|
||||
'certificates',
|
||||
'emergency_contact_name',
|
||||
'emergency_contact_relationship',
|
||||
];
|
||||
|
||||
// Array/JSON Cast for dynamic Multi-file storage
|
||||
protected $casts = [
|
||||
'certificates' => 'array',
|
||||
'dob' => 'date',
|
||||
];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class CourseAssignStudent extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
// Database table name
|
||||
protected $table = 'course_assign_student';
|
||||
|
||||
// Mass assignable attributes
|
||||
protected $fillable = [
|
||||
'student_id',
|
||||
'course_id',
|
||||
'assigned_at',
|
||||
];
|
||||
|
||||
/**
|
||||
* Relationship: Student Details
|
||||
*/
|
||||
public function studentDetail()
|
||||
{
|
||||
return $this->belongsTo(StudentDetail::class, 'student_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship: Course
|
||||
*/
|
||||
public function course()
|
||||
{
|
||||
return $this->belongsTo(Course::class, 'course_id');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Notification extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'message',
|
||||
'type',
|
||||
'link',
|
||||
'is_read',
|
||||
'target_role',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Result extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'results';
|
||||
|
||||
protected $fillable = [
|
||||
'student_log_id',
|
||||
'module_code',
|
||||
'academic_year',
|
||||
'semester',
|
||||
'module_name',
|
||||
'marks',
|
||||
'grade',
|
||||
'status',
|
||||
|
||||
];
|
||||
}
|
||||
|
|
@ -2,24 +2,37 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class StudentPortalLog extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'student_portal_logs';
|
||||
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'email',
|
||||
'phone',
|
||||
'studentid',
|
||||
'password',
|
||||
'pin',
|
||||
'status',
|
||||
];
|
||||
|
||||
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'pin',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the user associated with this portal log.
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Timetable extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'timetables';
|
||||
|
||||
protected $fillable = [
|
||||
'student_log_id',
|
||||
'time_slot',
|
||||
'day',
|
||||
'subject_name',
|
||||
'type',
|
||||
'sort_order',
|
||||
];
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ class User extends Authenticatable
|
|||
'email',
|
||||
'phone',
|
||||
'password',
|
||||
'email_otp',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class adminlogin extends Model
|
||||
{
|
||||
protected $table = 'adminlogins';
|
||||
|
||||
protected $fillable = [
|
||||
'username',
|
||||
'password',
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
'password',
|
||||
];
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class courseModules extends Model
|
||||
{
|
||||
//
|
||||
}
|
||||
|
|
@ -2,9 +2,39 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class courses extends Model
|
||||
{
|
||||
//
|
||||
use HasFactory;
|
||||
|
||||
|
||||
protected $table = 'courses';
|
||||
|
||||
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'image',
|
||||
'duration',
|
||||
'level',
|
||||
'author',
|
||||
'desc',
|
||||
'student',
|
||||
'rating',
|
||||
'badge',
|
||||
'trending',
|
||||
'course_code',
|
||||
'status'
|
||||
];
|
||||
|
||||
public function students()
|
||||
{
|
||||
return $this->belongsToMany(
|
||||
StudentDetail::class,
|
||||
'course_assign_student',
|
||||
'course_id',
|
||||
'student_details_id'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Module extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* Mass assignable attributes.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'course_id',
|
||||
'module_code',
|
||||
'title',
|
||||
'semester',
|
||||
'credits',
|
||||
'description',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the course that owns the module.
|
||||
*/
|
||||
public function course()
|
||||
{
|
||||
return $this->belongsTo(Course::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace App\Observers;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\StudentPortalLog;
|
||||
|
||||
class UserObserver
|
||||
{
|
||||
/**
|
||||
* Handle the User "created" event.
|
||||
*/
|
||||
public function created(User $user): void
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the User "updated" event.
|
||||
*/
|
||||
public function updated(User $user): void
|
||||
{
|
||||
|
||||
if ($user->isDirty('password')) {
|
||||
|
||||
StudentPortalLog::where('user_id', $user->id)
|
||||
->update([
|
||||
'password' => $user->password,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the User "deleted" event.
|
||||
*/
|
||||
public function deleted(User $user): void
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the User "restored" event.
|
||||
*/
|
||||
public function restored(User $user): void
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the User "force deleted" event.
|
||||
*/
|
||||
|
||||
public function forceDeleted(User $user): void
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,8 @@
|
|||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use App\Models\User;
|
||||
use App\Observers\UserObserver;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
|
@ -19,6 +21,6 @@ class AppServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
//
|
||||
User::observe(UserObserver::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,10 @@
|
|||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"barryvdh/laravel-dompdf": "^3.1",
|
||||
"laravel/framework": "^12.0",
|
||||
"laravel/tinker": "^2.10.1"
|
||||
"laravel/tinker": "^2.10.1",
|
||||
"maatwebsite/excel": "^3.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.23",
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -11,12 +11,18 @@ return new class extends Migration
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('student_portal_logs', function (Blueprint $table) {
|
||||
$table->foreignId('user_id')
|
||||
->nullable()
|
||||
->after('email')
|
||||
->constrained('users')
|
||||
->onDelete('cascade');
|
||||
Schema::create('student_portal_logs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('user_id')->nullable()->constrained('users')->onDelete('cascade');
|
||||
$table->string('first_name')->nullable();
|
||||
$table->string('last_name')->nullable();
|
||||
$table->string('email');
|
||||
$table->string('phone')->nullable();
|
||||
$table->string('studentid')->nullable();
|
||||
$table->string('password')->nullable();
|
||||
$table->string('pin')->nullable();
|
||||
$table->string('status')->default('active');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -25,9 +31,6 @@ return new class extends Migration
|
|||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('student_portal_logs', function (Blueprint $table) {
|
||||
$table->dropForeign(['user_id']);
|
||||
$table->dropColumn('user_id');
|
||||
});
|
||||
Schema::dropIfExists('student_portal_logs');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->string('email_otp')->nullable()->after('password');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('email_otp');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('applications', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('user_id')->constrained()->onDelete('cascade');
|
||||
|
||||
// Student Info
|
||||
$table->string('first_name');
|
||||
$table->string('last_name');
|
||||
$table->string('nic')->nullable();
|
||||
$table->string('nationality')->nullable();
|
||||
$table->string('address');
|
||||
$table->string('state');
|
||||
$table->string('gender')->nullable();
|
||||
$table->date('dob')->nullable();
|
||||
|
||||
// Contact Info
|
||||
$table->string('mobile');
|
||||
$table->string('mobile2')->nullable();
|
||||
$table->string('email');
|
||||
$table->string('preferred_contact_method')->nullable();
|
||||
|
||||
// Academic Qualifications
|
||||
$table->string('still_at_school')->nullable();
|
||||
$table->string('highest_qualification')->nullable();
|
||||
$table->string('school_name')->nullable();
|
||||
$table->integer('year_completed')->nullable();
|
||||
$table->string('exam_passed')->nullable();
|
||||
$table->string('subjects')->nullable();
|
||||
$table->text('grades_results')->nullable();
|
||||
$table->json('certificates')->nullable(); // Multi-file paths JSON row එකක් ලෙස
|
||||
|
||||
// Emergency Contacts
|
||||
$table->string('emergency_contact_name');
|
||||
$table->string('emergency_contact_relationship');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('applications');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('results', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('student_log_id')->constrained('student_portal_logs')->onDelete('cascade');
|
||||
$table->string('module_code');
|
||||
$table->string('academic_year');
|
||||
$table->string('semester');
|
||||
$table->string('module_name');
|
||||
$table->integer('marks');
|
||||
$table->string('grade');
|
||||
$table->string('status')->default('Pass');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('results');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('timetables', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->unsignedBigInteger('student_log_id')->nullable();
|
||||
$table->string('time_slot');
|
||||
$table->string('day');
|
||||
$table->string('subject_name');
|
||||
$table->enum('type', ['Theory', 'Practical', 'Workshop', 'Break'])->default('Theory');
|
||||
$table->integer('sort_order')->default(1);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('timetables');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('adminlogins', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('username')->unique();
|
||||
$table->string('password');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('adminlogins');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('notifications', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('title');
|
||||
$table->text('message');
|
||||
$table->string('type')->default('info');
|
||||
$table->string('link')->nullable();
|
||||
$table->boolean('is_read')->default(false);
|
||||
$table->string('target_role')->default('admin');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('notifications');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('modules', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('course_id')->constrained()->onDelete('cascade');
|
||||
$table->string('title');
|
||||
$table->text('description')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('modules');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('modules', function (Blueprint $table) {
|
||||
$table->string('semester')->after('title')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('modules', function (Blueprint $table) {
|
||||
$table->dropColumn('semester');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('course_modules', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('course_id')->constrained('courses')->onDelete('cascade');
|
||||
$table->string('module_code');
|
||||
$table->string('title');
|
||||
$table->string('semester');
|
||||
$table->integer('credits')->nullable();
|
||||
$table->text('description')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('course_modules');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('course_assign_student', function (Blueprint $table) {
|
||||
$table->foreignId('student_id')->constrained('student_details')->onDelete('cascade');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('course_assign_student', function (Blueprint $table) {
|
||||
$table->dropForeign(['student_id']);
|
||||
$table->dropColumn('student_id');
|
||||
});
|
||||
}
|
||||
};
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
|
|
@ -4,102 +4,126 @@
|
|||
|
||||
@section('content')
|
||||
|
||||
<!-- Bootstrap 5 -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<!-- Google Font -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--theme-navy: #2D355B;
|
||||
--theme-navy-dark: #1F2541;
|
||||
--theme-red: #822424;
|
||||
--theme-red-hover: #df2c3e;
|
||||
--theme-yellow: #FFEA85;
|
||||
--bg-light: #F6F6F6;
|
||||
--white: #ffffff;
|
||||
}
|
||||
|
||||
body {
|
||||
background:#f6f7fb;
|
||||
font-family: 'Poppins', sans-serif;
|
||||
background: var(--bg-light);
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.feedback-header {
|
||||
background:linear-gradient(135deg,#5E244E,#4a1c3e);
|
||||
color:white;
|
||||
padding:40px;
|
||||
border-radius:20px;
|
||||
margin-bottom:35px;
|
||||
box-shadow:0 15px 35px rgba(0,0,0,.12);
|
||||
background: linear-gradient(135deg, #2B293F 0%, #94A6F959 100%) !important;
|
||||
color: var(--white);
|
||||
padding: 35px 30px;
|
||||
border-radius: 16px;
|
||||
margin-bottom: 30px;
|
||||
box-shadow: 0 8px 25px rgba(31, 37, 65, 0.15);
|
||||
border-left: 5px solid var(--theme-red);
|
||||
}
|
||||
|
||||
.feedback-header h2{
|
||||
font-weight:700;
|
||||
}
|
||||
|
||||
.feedback-header p{
|
||||
color:#ddd;
|
||||
}
|
||||
|
||||
/* Cards */
|
||||
.feedback-card {
|
||||
background:#fff;
|
||||
border-radius:20px;
|
||||
border:none;
|
||||
background: var(--white);
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 16px;
|
||||
padding: 30px;
|
||||
box-shadow:0 10px 30px rgba(0,0,0,.08);
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, .04);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
color:#5E244E;
|
||||
color: var(--theme-navy);
|
||||
font-weight: 700;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.card-title i {
|
||||
color:#d4af37;
|
||||
color: var(--theme-red);
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
/* Inputs */
|
||||
.form-control,
|
||||
.form-select{
|
||||
border-radius:15px;
|
||||
padding:12px;
|
||||
border:1px solid #ddd;
|
||||
.form-label {
|
||||
font-weight: 600;
|
||||
color: var(--theme-navy);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.form-control:focus,
|
||||
.form-select:focus{
|
||||
border-color:#744a68;
|
||||
box-shadow:0 0 0 .2rem rgba(94,36,78,.15);
|
||||
.form-control, .form-select {
|
||||
border-radius: 10px;
|
||||
padding: 12px 15px;
|
||||
border: 1px solid #cbd5e1;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Button */
|
||||
.submit-btn {
|
||||
background:#5E244E;
|
||||
color:white;
|
||||
background: var(--theme-red) !important;
|
||||
color: var(--white) !important;
|
||||
border: none;
|
||||
border-radius:50px;
|
||||
border-radius: 8px;
|
||||
padding: 12px 30px;
|
||||
font-weight: 600;
|
||||
transition: all 0.2s ease;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.submit-btn:hover {
|
||||
background:#4a1c3e;
|
||||
color:#fff;
|
||||
background: var(--theme-red-hover) !important;
|
||||
color: var(--white) !important;
|
||||
}
|
||||
|
||||
/* History */
|
||||
.history-card {
|
||||
margin-top: 35px;
|
||||
background:white;
|
||||
border-radius:20px;
|
||||
background: var(--white);
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
box-shadow:0 10px 30px rgba(0,0,0,.08);
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, .04);
|
||||
}
|
||||
|
||||
.history-head {
|
||||
background:#5E244E;
|
||||
color:white;
|
||||
background: var(--theme-navy);
|
||||
color: var(--white);
|
||||
padding: 18px 25px;
|
||||
}
|
||||
|
||||
.table th {
|
||||
background: #f8fafc;
|
||||
color: var(--theme-navy);
|
||||
font-weight: 600;
|
||||
border-bottom: 2px solid #e2e8f0;
|
||||
padding: 14px 20px;
|
||||
}
|
||||
|
||||
.table td {
|
||||
vertical-align: middle;
|
||||
padding: 14px 20px;
|
||||
}
|
||||
|
||||
.badge-status {
|
||||
padding:7px 15px;
|
||||
border-radius:50px;
|
||||
font-size:13px;
|
||||
padding: 6px 14px;
|
||||
border-radius: 30px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.pending {
|
||||
background:#fff3cd;
|
||||
background: rgba(255, 234, 133, 0.4);
|
||||
color: #856404;
|
||||
}
|
||||
|
||||
|
|
@ -113,89 +137,28 @@ body{
|
|||
|
||||
<!-- Header -->
|
||||
<div class="feedback-header">
|
||||
<h2><i class="fas fa-comments"></i> Feedback & Complaint</h2>
|
||||
<p> Share your suggestions, feedback, or complaints with the
|
||||
Automobile Engineering Academy management team.</p>
|
||||
<h2 class="mb-1"><i class="fas fa-comments me-2" style="color: var(--theme-yellow);"></i> Feedback & Complaint</h2>
|
||||
<p>Share your suggestions, feedback, or complaints with the Automobile Engineering Academy management team.</p>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
<!-- Feedback Form -->
|
||||
<div class="col-lg-6">
|
||||
<div class="feedback-card">
|
||||
<h4 class="card-title"><i class="fas fa-star"></i> Submit Feedback</h4>
|
||||
<form id="feedbackForm" action="{{ route('feedback.store') }}" method="POST">
|
||||
@csrf
|
||||
<div class="mb-3">
|
||||
<label class="form-label"> Feedback Type </label>
|
||||
<!-- Added name="feedback_type" -->
|
||||
<select class="form-select" id="feedbackType" name="feedback_type" required>
|
||||
<option value=""> Select Type </option>
|
||||
<option value="Course">Course</option>
|
||||
<option value="Lecturer">Lecturer </option>
|
||||
<option value="Workshop">Workshop </option>
|
||||
<option value="Facilities"> Facilities </option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Subject </label>
|
||||
<!-- Added name="subject" -->
|
||||
<input type="text" class="form-control" id="feedbackSubject" name="subject" placeholder="Enter subject" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Your Feedback </label>
|
||||
<!-- Added name="feedback_text" -->
|
||||
<textarea class="form-control" id="feedbackText" name="feedback_text" rows="5" placeholder="Write your feedback" required></textarea>
|
||||
</div>
|
||||
<button type="submit" class="submit-btn">
|
||||
<i class="fas fa-paper-plane"></i>Submit Feedback
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Complaint Form -->
|
||||
<!-- <div class="col-lg-6">
|
||||
<div class="feedback-card">
|
||||
<h4 class="card-title"><i class="fas fa-exclamation-triangle"></i> Submit Complaint</h4>
|
||||
<form id="complaintForm">
|
||||
<div class="mb-3">
|
||||
<label class="form-label"> Complaint Category</label>
|
||||
<select class="form-select" id="complaintCategory" required>
|
||||
<option value="">Select Category </option>
|
||||
<option value="Academic Issue"> Academic Issue</option>
|
||||
<option value="Staff Issue">Staff Issue </option>
|
||||
<option value="Technical Issue">Technical Issue</option>
|
||||
<option value="Other">Other</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label"> Complaint Title </label>
|
||||
<input type="text" class="form-control" id="complaintTitle" placeholder="Enter complaint title" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label"> Complaint Details</label>
|
||||
<textarea class="form-control" id="complaintDetails" rows="5" placeholder="Explain your complaint" required></textarea>
|
||||
</div>
|
||||
<button type="submit" class="submit-btn">
|
||||
<i class="fas fa-paper-plane"></i>Submit Complaint
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<form id="feedbackForm" action="{{ route('feedback.store') }}" method="POST">
|
||||
@csrf
|
||||
|
||||
|
||||
<!-- Alert Messages -->
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
{{ session('success') }}
|
||||
<div class="alert alert-success alert-dismissible fade show rounded-3 mb-4" role="alert">
|
||||
<i class="fas fa-check-circle me-2"></i>{{ session('success') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(session('error'))
|
||||
<div class="alert alert-danger alert-dismissible fade show rounded-3 mb-4" role="alert">
|
||||
<i class="fas fa-exclamation-circle me-2"></i>{{ session('error') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul class="mb-0">
|
||||
<div class="alert alert-danger rounded-3 mb-4">
|
||||
<ul class="mb-0 ps-3">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
|
|
@ -203,6 +166,15 @@ body{
|
|||
</div>
|
||||
@endif
|
||||
|
||||
<div class="row g-4">
|
||||
<!-- Feedback Form -->
|
||||
<div class="col-lg-6">
|
||||
<div class="feedback-card">
|
||||
<h4 class="card-title"><i class="fas fa-star"></i> Submit Feedback</h4>
|
||||
|
||||
<form id="feedbackForm" action="{{ route('feedback.store') }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label"> Feedback Type </label>
|
||||
<select class="form-select" id="feedbackType" name="feedback_type" required>
|
||||
|
|
@ -219,24 +191,64 @@ body{
|
|||
<input type="text" class="form-control" id="feedbackSubject" name="subject" value="{{ old('subject') }}" placeholder="Enter subject" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="mb-4">
|
||||
<label class="form-label">Your Feedback </label>
|
||||
<textarea class="form-control" id="feedbackText" name="feedback_text" rows="5" placeholder="Write your feedback" required>{{ old('feedback_text') }}</textarea>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="submit-btn">
|
||||
<i class="fas fa-paper-plane"></i> Submit Feedback
|
||||
<button type="submit" class="submit-btn shadow-sm">
|
||||
<i class="fas fa-paper-plane me-2"></i>Submit Feedback
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Previous History Table -->
|
||||
<!-- Complaint Form -->
|
||||
<div class="col-lg-6">
|
||||
<div class="feedback-card">
|
||||
<h4 class="card-title"><i class="fas fa-exclamation-triangle"></i> Submit Complaint</h4>
|
||||
|
||||
<form id="complaintForm" action="{{ route('feedback.store') }}" method="POST">
|
||||
@csrf
|
||||
<input type="hidden" name="is_complaint" value="1">
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label"> Complaint Category</label>
|
||||
<select class="form-select" id="complaintCategory" name="complaint_category" required>
|
||||
<option value="">Select Category </option>
|
||||
<option value="Academic Issue"> Academic Issue</option>
|
||||
<option value="Staff Issue">Staff Issue </option>
|
||||
<option value="Technical Issue">Technical Issue</option>
|
||||
<option value="Other">Other</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label"> Complaint Title </label>
|
||||
<input type="text" class="form-control" id="complaintTitle" name="complaint_title" placeholder="Enter complaint title" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label"> Complaint Details</label>
|
||||
<textarea class="form-control" id="complaintDetails" name="complaint_details" rows="5" placeholder="Explain your complaint" required></textarea>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="submit-btn shadow-sm">
|
||||
<i class="fas fa-paper-plane me-2"></i>Submit Complaint
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dynamic History Table -->
|
||||
<div class="history-card">
|
||||
<div class="history-head">
|
||||
<h4 class="mb-0"><i class="fas fa-history"></i> Previous Requests</h4>
|
||||
<h5 class="m-0"><i class="fas fa-history me-2" style="color: var(--theme-yellow);"></i> Previous Requests</h5>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th> Type </th>
|
||||
|
|
@ -247,18 +259,31 @@ body{
|
|||
</thead>
|
||||
|
||||
<tbody id="historyTableBody">
|
||||
@forelse ($feedbacks as $item)
|
||||
<tr>
|
||||
<td>Feedback</td>
|
||||
<td>Workshop Equipment </td>
|
||||
<td>10 July 2026</td>
|
||||
<td><span class="badge-status resolved"> Resolved</span></td>
|
||||
<td>
|
||||
<span class="fw-semibold" style="color: var(--theme-navy);">
|
||||
{{ $item->feedback_type }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ $item->subject }}</td>
|
||||
<td>{{ \Carbon\Carbon::parse($item->created_at)->format('d M Y') }}</td>
|
||||
<td>
|
||||
@if(strtolower($item->status) == 'resolved')
|
||||
<span class="badge-status resolved"><i class="fas fa-check me-1"></i> Resolved</span>
|
||||
@else
|
||||
<span class="badge-status pending"><i class="fas fa-clock me-1"></i> {{ $item->status ?? 'Pending' }}</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td>Complaint</td>
|
||||
<td>Class Schedule Issue </td>
|
||||
<td>05 July 2026 </td>
|
||||
<td><span class="badge-status pending"> Pending </span></td>
|
||||
<td colspan="4" class="text-center py-4 text-muted">
|
||||
<i class="fas fa-inbox fa-2x mb-2 d-block"></i>
|
||||
No feedback or complaints submitted yet.
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -266,6 +291,4 @@ body{
|
|||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@endsection
|
||||
|
|
@ -1,310 +1,554 @@
|
|||
@extends('layouts.studentportalnav')
|
||||
|
||||
@section('title','Dashboard')
|
||||
@section('title', 'Student Dashboard')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--primary:#5E244E;
|
||||
--secondary:#8B3A74;
|
||||
--light:#f5f6fb;
|
||||
--dark:#2d2d2d;
|
||||
--theme-navy: #1E233E;
|
||||
--theme-navy-dark: #15182C;
|
||||
--theme-red: #822424;
|
||||
--theme-red-hover: #df2c3e;
|
||||
--theme-yellow: #FFEA85;
|
||||
--theme-bg: #F4F6F9;
|
||||
--text-dark: #1E293B;
|
||||
}
|
||||
|
||||
body{
|
||||
background:var(--light);
|
||||
/* Welcome Banner */
|
||||
.welcome-banner {
|
||||
background: linear-gradient(135deg, #1E233E 0%, #2A1F3B 50%, #4A1A24 100%);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: none;
|
||||
box-shadow: 0 10px 30px rgba(30, 35, 62, 0.15);
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.dashboard-header{
|
||||
display:flex;
|
||||
justify-content:space-between;
|
||||
align-items:center;
|
||||
margin-bottom:30px;
|
||||
}
|
||||
|
||||
.dashboard-header h2{
|
||||
font-weight:700;
|
||||
color:var(--dark);
|
||||
}
|
||||
|
||||
.dashboard-header p{
|
||||
color:#777;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
.avatar{
|
||||
width:55px;
|
||||
height:55px;
|
||||
.welcome-banner::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
right: -10%;
|
||||
width: 350px;
|
||||
height: 350px;
|
||||
background: radial-gradient(circle, rgba(255, 234, 133, 0.12) 0%, rgba(255, 234, 133, 0) 70%);
|
||||
border-radius: 50%;
|
||||
background:var(--primary);
|
||||
color:#fff;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.user-avatar-badge {
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.avatar-circle {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
border-radius: 14px;
|
||||
background: linear-gradient(135deg, #FFEA85 0%, #F59E0B 100%);
|
||||
color: #1E233E;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight:bold;
|
||||
font-size:20px;
|
||||
}
|
||||
|
||||
/* Statistic Cards */
|
||||
|
||||
.stat-card{
|
||||
background:#fff;
|
||||
border-radius:15px;
|
||||
padding:25px;
|
||||
box-shadow:0 8px 20px rgba(0,0,0,.08);
|
||||
transition:.3s;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.stat-card:hover{
|
||||
transform:translateY(-6px);
|
||||
}
|
||||
|
||||
.stat-icon{
|
||||
width:60px;
|
||||
height:60px;
|
||||
border-radius:12px;
|
||||
display:flex;
|
||||
justify-content:center;
|
||||
align-items:center;
|
||||
color:#fff;
|
||||
font-weight: 800;
|
||||
font-size: 22px;
|
||||
margin-bottom:20px;
|
||||
box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);
|
||||
}
|
||||
|
||||
.stat-card h3{
|
||||
font-weight:700;
|
||||
margin-bottom:5px;
|
||||
/* Stat Cards Modern */
|
||||
.stat-card-modern {
|
||||
background: #ffffff;
|
||||
border-radius: 16px;
|
||||
padding: 24px;
|
||||
border: 1px solid #E2E8F0;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.03);
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
position: relative;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.stat-card p{
|
||||
color:#777;
|
||||
margin:0;
|
||||
.stat-card-modern:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 12px 28px rgba(30, 35, 62, 0.1);
|
||||
border-color: rgba(30, 35, 62, 0.2);
|
||||
}
|
||||
|
||||
/* Services */
|
||||
.stat-icon-wrapper {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
border-radius: 14px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #ffffff;
|
||||
font-size: 22px;
|
||||
box-shadow: 0 6px 14px rgba(0,0,0,0.12);
|
||||
}
|
||||
|
||||
.section-title{
|
||||
.stat-number {
|
||||
font-size: 2.1rem;
|
||||
font-weight: 800;
|
||||
color: #0F172A;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 2px;
|
||||
letter-spacing: -0.5px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
color: #64748B;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Section Title Accent */
|
||||
.title-accent {
|
||||
width: 6px;
|
||||
height: 24px;
|
||||
background: linear-gradient(180deg, var(--theme-red) 0%, var(--theme-red-hover) 100%);
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Modern Service Card */
|
||||
.service-card-modern {
|
||||
background: #ffffff;
|
||||
border-radius: 16px;
|
||||
padding: 28px 24px;
|
||||
border: 1px solid #E2E8F0;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.03);
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.service-card-modern:hover {
|
||||
transform: translateY(-6px);
|
||||
box-shadow: 0 16px 32px rgba(130, 36, 36, 0.1);
|
||||
border-color: rgba(130, 36, 36, 0.3);
|
||||
}
|
||||
|
||||
.service-icon-box {
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
border-radius: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
font-weight:bold;
|
||||
margin:40px 0 20px;
|
||||
margin-bottom: 20px;
|
||||
background: rgba(130, 36, 36, 0.08);
|
||||
color: var(--theme-red);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.service-card{
|
||||
background:#fff;
|
||||
border-radius:15px;
|
||||
padding:30px;
|
||||
text-align:center;
|
||||
transition:.3s;
|
||||
box-shadow:0 8px 20px rgba(0,0,0,.08);
|
||||
.service-card-modern:hover .service-icon-box {
|
||||
background: var(--theme-red);
|
||||
color: #ffffff;
|
||||
transform: scale(1.08);
|
||||
box-shadow: 0 6px 16px rgba(130, 36, 36, 0.3);
|
||||
}
|
||||
|
||||
.service-card-modern h5 {
|
||||
font-weight: 700;
|
||||
color: #0F172A;
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.service-card-modern p {
|
||||
color: #64748B;
|
||||
font-size: 0.88rem;
|
||||
margin: 0;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.action-link {
|
||||
font-weight: 700;
|
||||
font-size: 0.85rem;
|
||||
color: var(--theme-red);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-top: 18px;
|
||||
transition: gap 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
.service-card-modern:hover .action-link {
|
||||
gap: 10px;
|
||||
color: var(--theme-red-hover);
|
||||
}
|
||||
|
||||
/* Document Card */
|
||||
.doc-card {
|
||||
background: #ffffff;
|
||||
border-radius: 16px;
|
||||
padding: 24px 20px;
|
||||
border: 1px solid #E2E8F0;
|
||||
box-shadow: 0 4px 16px rgba(0,0,0,0.03);
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.service-card:hover{
|
||||
transform:translateY(-8px);
|
||||
.doc-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 12px 24px rgba(0,0,0,0.08);
|
||||
border-color: #CBD5E1;
|
||||
}
|
||||
|
||||
.service-card i{
|
||||
font-size:45px;
|
||||
color:var(--primary);
|
||||
margin-bottom:20px;
|
||||
}
|
||||
|
||||
.service-card h5{
|
||||
font-weight:700;
|
||||
}
|
||||
|
||||
.service-card p{
|
||||
color:#777;
|
||||
font-size:14px;
|
||||
.doc-icon-badge {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
border-radius: 14px;
|
||||
background: #FEF2F2;
|
||||
color: #DC2626;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
margin: 0 auto 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container-fluid">
|
||||
|
||||
<div class="dashboard-header">
|
||||
<div class="portal-content-container">
|
||||
|
||||
<!-- Welcome Hero Banner -->
|
||||
<div class="welcome-banner card rounded-4 mb-4">
|
||||
<div class="card-body p-4 p-lg-5 d-flex align-items-center justify-content-between flex-wrap gap-3 position-relative" style="z-index: 1;">
|
||||
<div>
|
||||
<h2>Welcome Back, student
|
||||
<p>Manage your academic activities from your dashboard.</p>
|
||||
<div class="d-flex align-items-center gap-2 mb-2 flex-wrap">
|
||||
<span class="badge bg-success bg-opacity-20 text-success border border-success border-opacity-20 px-3 py-2 rounded-pill fw-semibold" style="font-size: 0.78rem;">
|
||||
<i class="fa-solid fa-circle me-1" style="font-size: 7px; vertical-align: middle;"></i> Active Academic Year 2026
|
||||
</span>
|
||||
<span class="text-white-50 small"><i class="fa-regular fa-calendar me-1"></i> {{ date('l, F j, Y') }}</span>
|
||||
</div>
|
||||
<h2 class="fw-bold text-white mb-2" style="letter-spacing: -0.5px;">
|
||||
Welcome Back, {{ Auth::check() ? Auth::user()->first_name : 'Student' }}! 👋
|
||||
</h2>
|
||||
<p class="text-white-50 mb-0 fs-6" style="max-width: 580px;">
|
||||
Manage your academic activities, course schedules, and exam performance directly from your portal dashboard.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- <div class="avatar">
|
||||
S
|
||||
</div> -->
|
||||
|
||||
@if(Auth::check())
|
||||
<div class="user-avatar-badge d-flex align-items-center gap-3 bg-white bg-opacity-10 p-3 rounded-4 backdrop-blur border border-white border-opacity-10">
|
||||
<div class="avatar-circle">
|
||||
{{ strtoupper(substr(Auth::user()->first_name, 0, 1)) }}
|
||||
</div>
|
||||
|
||||
<!-- Statistics -->
|
||||
|
||||
<div class="row g-4">
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="stat-card">
|
||||
|
||||
<div class="stat-icon" style="background:#5E244E;">
|
||||
<i class="fa-solid fa-book"></i>
|
||||
<div class="text-white d-none d-sm-block">
|
||||
<div class="fw-bold fs-6">{{ Auth::user()->first_name }} {{ Auth::user()->last_name }}</div>
|
||||
<div class="small fst-italic text-warning opacity-75" style="font-size: 11px;">{{ Auth::user()->email }}</div>
|
||||
</div>
|
||||
|
||||
<h3>6</h3>
|
||||
<p>Enrolled Courses</p>
|
||||
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="stat-card">
|
||||
<!-- Key Performance Metrics (Stat Cards) -->
|
||||
<div class="row g-3 g-lg-4 mb-4">
|
||||
|
||||
<div class="stat-icon" style="background:#0d9488;">
|
||||
<i class="fa-solid fa-file-lines"></i>
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<div class="stat-card-modern">
|
||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||
<div class="stat-icon-wrapper" style="background: linear-gradient(135deg, #3B82F6 0%, #1D4ED8 100%);">
|
||||
<i class="fa-solid fa-book-open-reader"></i>
|
||||
</div>
|
||||
<span class="badge bg-primary-subtle text-primary border border-primary-subtle px-2.5 py-1.5 rounded-pill fw-semibold" style="font-size: 0.75rem;">
|
||||
<i class="fa-solid fa-circle-check me-1"></i> Active
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="stat-number">6</div>
|
||||
<div class="stat-label">Enrolled Courses</div>
|
||||
</div>
|
||||
|
||||
<h3>3</h3>
|
||||
<p>Assignments</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="stat-card">
|
||||
|
||||
<div class="stat-icon" style="background:#d97706;">
|
||||
<i class="fa-solid fa-chart-column"></i>
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<div class="stat-card-modern">
|
||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||
<div class="stat-icon-wrapper" style="background: linear-gradient(135deg, #10B981 0%, #047857 100%);">
|
||||
<i class="fa-solid fa-file-signature"></i>
|
||||
</div>
|
||||
<span class="badge bg-warning-subtle text-warning border border-warning-subtle px-2.5 py-1.5 rounded-pill fw-semibold" style="font-size: 0.75rem;">
|
||||
<i class="fa-solid fa-clock me-1"></i> Pending
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="stat-number">3</div>
|
||||
<div class="stat-label">Assignments Due</div>
|
||||
</div>
|
||||
|
||||
<h3>78%</h3>
|
||||
<p>Average Result</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="stat-card">
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<div class="stat-card-modern">
|
||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||
<div class="stat-icon-wrapper" style="background: linear-gradient(135deg, #F59E0B 0%, #B45309 100%);">
|
||||
<i class="fa-solid fa-chart-line"></i>
|
||||
</div>
|
||||
<span class="badge bg-success-subtle text-success border border-success-subtle px-2.5 py-1.5 rounded-pill fw-semibold" style="font-size: 0.75rem;">
|
||||
<i class="fa-solid fa-arrow-trend-up me-1"></i> Grade B+
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="stat-number">78%</div>
|
||||
<div class="stat-label">Average Result</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-icon" style="background:#dc2626;">
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<div class="stat-card-modern">
|
||||
<div class="d-flex align-items-center justify-content-between mb-3">
|
||||
<div class="stat-icon-wrapper" style="background: linear-gradient(135deg, #EF4444 0%, #B91C1C 100%);">
|
||||
<i class="fa-solid fa-bell"></i>
|
||||
</div>
|
||||
|
||||
<h3>2</h3>
|
||||
<p>Exam Notices</p>
|
||||
|
||||
<span class="badge bg-danger-subtle text-danger border border-danger-subtle px-2.5 py-1.5 rounded-pill fw-semibold" style="font-size: 0.75rem;">
|
||||
<i class="fa-solid fa-bullhorn me-1"></i> Upcoming
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="stat-number">2</div>
|
||||
<div class="stat-label">Exam Notices</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Services -->
|
||||
|
||||
<div class="section-title">
|
||||
Student Services
|
||||
<div class="col-lg-5" id="notifications-section" style="width: 100%;">
|
||||
<div class="card border-0 shadow-sm rounded-3 h-100">
|
||||
<div class="card-header bg-white py-3 border-0 d-flex justify-content-between align-items-center">
|
||||
<h5 class="fw-bold mb-0 text-dark">
|
||||
<i class="fa-solid fa-bell text-danger me-2"></i>System Notifications
|
||||
</h5>
|
||||
<span class="badge bg-danger rounded-pill">{{ $unreadNotifications ?? 0 }} Unread</span>
|
||||
</div>
|
||||
<div class="card-body p-0" style="max-height: 450px; overflow-y: auto;">
|
||||
<ul class="list-group list-group-flush">
|
||||
@forelse($notifications ?? [] as $notification)
|
||||
<li class="list-group-item p-3 border-bottom {{ $notification->is_read ? 'bg-light text-muted' : 'bg-white' }}">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<div class="me-2">
|
||||
{{-- Type Badge --}}
|
||||
@if($notification->type == 'success')
|
||||
<span class="badge bg-success mb-1">Success</span>
|
||||
@elseif($notification->type == 'warning')
|
||||
<span class="badge bg-warning text-dark mb-1">Warning</span>
|
||||
@else
|
||||
<span class="badge bg-info text-dark mb-1">Info</span>
|
||||
@endif
|
||||
|
||||
<h6 class="fw-bold mb-1 {{ $notification->is_read ? 'text-secondary' : 'text-dark' }}">
|
||||
{{ $notification->title }}
|
||||
</h6>
|
||||
<p class="mb-1 text-muted small">{{ $notification->message }}</p>
|
||||
|
||||
|
||||
<small class="text-secondary opacity-75 d-block" style="font-size: 11px;">
|
||||
<i class="fa-regular fa-clock me-1"></i>{{ $notification->created_at->diffForHumans() }}
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
{{-- Mark as Read Button --}}
|
||||
@if(!$notification->is_read)
|
||||
<form action="{{ route('admin.notifications.read', $notification->id) }}" method="POST">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-sm btn-outline-success border-0 rounded-circle" title="Mark as Read">
|
||||
<i class="fa-solid fa-check"></i>
|
||||
</button>
|
||||
</form>
|
||||
@else
|
||||
<span class="text-muted" title="Read"><i class="fa-solid fa-check-double text-secondary"></i></span>
|
||||
@endif
|
||||
</div>
|
||||
</li>
|
||||
@empty
|
||||
<li class="list-group-item text-center py-4 text-muted">
|
||||
<i class="fa-solid fa-inbox fs-3 d-block mb-2 text-secondary"></i>
|
||||
No notifications found.
|
||||
</li>
|
||||
@endforelse
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Student Services Grid -->
|
||||
<div class="mb-4">
|
||||
<h5 class="fw-bold text-dark mb-3 d-flex align-items-center gap-2">
|
||||
<span class="title-accent"></span> Student Services & Quick Actions
|
||||
</h5>
|
||||
|
||||
<div class="row g-3 g-lg-4">
|
||||
|
||||
<div class="col-lg-4 col-md-6">
|
||||
<a href="/mycourse" class="text-decoration-none" style="color:#5E244E">
|
||||
|
||||
<div class="service-card">
|
||||
|
||||
<i class="fa-solid fa-book"></i>
|
||||
|
||||
<a href="/mycourse" class="service-card-modern">
|
||||
<div>
|
||||
<div class="service-icon-box">
|
||||
<i class="fa-solid fa-book-bookmark"></i>
|
||||
</div>
|
||||
<h5>My Courses</h5>
|
||||
|
||||
<p>Access all learning materials and course content.</p>
|
||||
|
||||
<p>Access all registered learning modules, video lectures, and syllabus materials.</p>
|
||||
</div>
|
||||
<div class="action-link">
|
||||
Explore Courses <i class="fa-solid fa-arrow-right"></i>
|
||||
</div>
|
||||
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 col-md-6">
|
||||
<a href="/timetable" class="text-decoration-none" style="color:#5E244E">
|
||||
|
||||
<div class="service-card">
|
||||
|
||||
<a href="/timetable" class="service-card-modern">
|
||||
<div>
|
||||
<div class="service-icon-box">
|
||||
<i class="fa-solid fa-calendar-days"></i>
|
||||
|
||||
</div>
|
||||
<h5>Class Timetable</h5>
|
||||
|
||||
<p>View your weekly lecture timetable.</p>
|
||||
|
||||
<p>Check your weekly lecture schedules, classroom locations, and timing updates.</p>
|
||||
</div>
|
||||
<div class="action-link">
|
||||
View Schedule <i class="fa-solid fa-arrow-right"></i>
|
||||
</div>
|
||||
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 col-md-6">
|
||||
<a href="/Assignments" class="text-decoration-none" style="color:#5E244E">
|
||||
|
||||
<div class="service-card">
|
||||
|
||||
<i class="fa-solid fa-file-lines"></i>
|
||||
|
||||
<h5>Assignments</h5>
|
||||
|
||||
<p>Submit and manage assignments.</p>
|
||||
|
||||
<a href="/results" class="service-card-modern">
|
||||
<div>
|
||||
<div class="service-icon-box">
|
||||
<i class="fa-solid fa-award"></i>
|
||||
</div>
|
||||
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 col-md-6">
|
||||
<a href="/results" class="text-decoration-none" style="color:#5E244E">
|
||||
|
||||
<div class="service-card">
|
||||
|
||||
<i class="fa-solid fa-square-poll-vertical"></i>
|
||||
|
||||
<h5>Exam Results</h5>
|
||||
|
||||
<p>Check semester examination results.</p>
|
||||
|
||||
<p>Review semester examination grades, transcript records, and academic progress.</p>
|
||||
</div>
|
||||
<div class="action-link">
|
||||
View Marks <i class="fa-solid fa-arrow-right"></i>
|
||||
</div>
|
||||
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 col-md-6">
|
||||
<a href="/Feedback&Complain" class="text-decoration-none"style="color:#5E244E">
|
||||
|
||||
<div class="service-card">
|
||||
<a href="/Studentguidelines" class="service-card-modern">
|
||||
<div>
|
||||
<div class="service-icon-box">
|
||||
<i class="fa-solid fa-book-open"></i>
|
||||
</div>
|
||||
<h5>Student Guidelines</h5>
|
||||
<p>Read campus rules, academic regulations, safety procedures, and code of conduct.</p>
|
||||
</div>
|
||||
<div class="action-link">
|
||||
Read Guidelines <i class="fa-solid fa-arrow-right"></i>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 col-md-6">
|
||||
<a href="/Feedback&Complain" class="service-card-modern">
|
||||
<div>
|
||||
<div class="service-icon-box">
|
||||
<i class="fa-solid fa-comments"></i>
|
||||
|
||||
<h5>Feedback & Complaint</h5>
|
||||
|
||||
<p>Send feedback and contact administration.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<h5>Feedback & Complaints</h5>
|
||||
<p>Submit inquiries, suggestions, or complaints directly to the student support team.</p>
|
||||
</div>
|
||||
<div class="action-link">
|
||||
Submit Inquiry <i class="fa-solid fa-arrow-right"></i>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4 col-md-6">
|
||||
|
||||
<a href="/StudentProfile" class="text-decoration-none"style="color:#5E244E">
|
||||
|
||||
<div class="service-card">
|
||||
|
||||
<i class="fa-solid fa-user"></i>
|
||||
|
||||
<!-- <a href="{{ route('StudentProfile') }}" class="text-decoration-none"style="color:#5E244E">
|
||||
<div class="service-card">
|
||||
<i class="fas fa-user"></i> Profile
|
||||
</a> -->
|
||||
<h5>Student Profile</h5>
|
||||
|
||||
<p>Update your personal information.</p>
|
||||
|
||||
<a href="/StudentProfile" class="service-card-modern">
|
||||
<div>
|
||||
<div class="service-icon-box">
|
||||
<i class="fa-solid fa-id-card"></i>
|
||||
</div>
|
||||
<h5>Student Profile</h5>
|
||||
<p>View and update your personal contact details, credentials, and security PIN.</p>
|
||||
</div>
|
||||
<div class="action-link">
|
||||
Manage Profile <i class="fa-solid fa-arrow-right"></i>
|
||||
</div>
|
||||
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Official Document Downloads Section -->
|
||||
<div class="mb-5">
|
||||
<h5 class="fw-bold text-dark mb-3 d-flex align-items-center gap-2">
|
||||
<span class="title-accent"></span> Official Academic Documents (PDF)
|
||||
</h5>
|
||||
|
||||
<div class="row g-3 g-lg-4">
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<a href="{{ route('student.download.calendar') }}" class="text-decoration-none" target="_blank">
|
||||
<div class="doc-card text-center">
|
||||
<div class="doc-icon-badge">
|
||||
<i class="fa-solid fa-file-pdf"></i>
|
||||
</div>
|
||||
<h6 class="fw-bold text-dark mb-1">Academic Calendar</h6>
|
||||
<small class="text-muted d-block mb-3">Semester dates & holidays</small>
|
||||
<span class="btn btn-sm btn-outline-danger rounded-pill px-3 fw-semibold">
|
||||
<i class="fa-solid fa-download me-1"></i> Download PDF
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<a href="{{ route('student.download.handbook') }}" class="text-decoration-none" target="_blank">
|
||||
<div class="doc-card text-center">
|
||||
<div class="doc-icon-badge">
|
||||
<i class="fa-solid fa-file-pdf"></i>
|
||||
</div>
|
||||
<h6 class="fw-bold text-dark mb-1">Student Handbook</h6>
|
||||
<small class="text-muted d-block mb-3">Campus rules & policies</small>
|
||||
<span class="btn btn-sm btn-outline-danger rounded-pill px-3 fw-semibold">
|
||||
<i class="fa-solid fa-download me-1"></i> Download PDF
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<a href="{{ route('student.download.examcode') }}" class="text-decoration-none" target="_blank">
|
||||
<div class="doc-card text-center">
|
||||
<div class="doc-icon-badge">
|
||||
<i class="fa-solid fa-file-pdf"></i>
|
||||
</div>
|
||||
<h6 class="fw-bold text-dark mb-1">Exam Code of Conduct</h6>
|
||||
<small class="text-muted d-block mb-3">Examination guidelines</small>
|
||||
<span class="btn btn-sm btn-outline-danger rounded-pill px-3 fw-semibold">
|
||||
<i class="fa-solid fa-download me-1"></i> Download PDF
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-xl-3 col-md-6">
|
||||
<a href="{{ route('student.download.helpdesk') }}" class="text-decoration-none" target="_blank">
|
||||
<div class="doc-card text-center">
|
||||
<div class="doc-icon-badge">
|
||||
<i class="fa-solid fa-file-pdf"></i>
|
||||
</div>
|
||||
<h6 class="fw-bold text-dark mb-1">Helpdesk Support Guide</h6>
|
||||
<small class="text-muted d-block mb-3">IT & portal assistance</small>
|
||||
<span class="btn btn-sm btn-outline-danger rounded-pill px-3 fw-semibold">
|
||||
<i class="fa-solid fa-download me-1"></i> Download PDF
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -4,23 +4,42 @@
|
|||
|
||||
@section('content')
|
||||
|
||||
<!-- Bootstrap 5 -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<!-- Google Font -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--theme-navy: #2D355B; /* Primary Navy */
|
||||
--theme-navy-dark: #1F2541; /* Dark Navy */
|
||||
--theme-red: #822424; /* Primary Accent Red */
|
||||
--theme-red-hover: #df2c3e; /* Red Hover */
|
||||
--theme-yellow: #FFEA85; /* Accent Yellow/Gold */
|
||||
--bg-light: #F6F6F6; /* Page Background */
|
||||
--white: #ffffff;
|
||||
}
|
||||
|
||||
body {
|
||||
background:#f6f7fb;
|
||||
font-family: 'Poppins', sans-serif;
|
||||
background: var(--bg-light);
|
||||
}
|
||||
|
||||
/*==========================
|
||||
Hero
|
||||
Hero Section
|
||||
===========================*/
|
||||
|
||||
.guideline-hero {
|
||||
background:linear-gradient(135deg,#5E244E,#4a1c3e);
|
||||
border-radius:20px;
|
||||
padding:45px;
|
||||
color:#fff;
|
||||
margin-bottom:35px;
|
||||
box-shadow:0 18px 40px rgba(0,0,0,.12);
|
||||
background: linear-gradient(135deg, #2B293F 0%, #94A6F959 100%) !important;
|
||||
border-radius: 16px;
|
||||
padding: 35px 30px;
|
||||
color: var(--white);
|
||||
margin-bottom: 30px;
|
||||
box-shadow: 0 8px 25px rgba(31, 37, 65, 0.15);
|
||||
border-left: 5px solid var(--theme-red);
|
||||
}
|
||||
|
||||
.guideline-hero h2 {
|
||||
|
|
@ -29,444 +48,304 @@ Hero
|
|||
}
|
||||
|
||||
.guideline-hero p {
|
||||
color:#ececec;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
margin-bottom: 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
/*==========================
|
||||
Cards
|
||||
Guide Cards
|
||||
===========================*/
|
||||
|
||||
.guide-card {
|
||||
|
||||
background:#fff;
|
||||
border:none;
|
||||
border-radius:20px;
|
||||
box-shadow:0 10px 30px rgba(0,0,0,.08);
|
||||
transition:.3s;
|
||||
background: var(--white);
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, .04);
|
||||
transition: all 0.3s ease;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
|
||||
}
|
||||
|
||||
.guide-card:hover {
|
||||
|
||||
transform:translateY(-6px);
|
||||
|
||||
transform: translateY(-4px);
|
||||
border-color: var(--theme-navy);
|
||||
box-shadow: 0 10px 22px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.card-head {
|
||||
|
||||
background:#5E244E;
|
||||
color:#fff;
|
||||
background: #753636;
|
||||
color: var(--white);
|
||||
padding: 18px 22px;
|
||||
|
||||
}
|
||||
|
||||
.card-head h5 {
|
||||
|
||||
margin: 0;
|
||||
font-weight: 600;
|
||||
|
||||
}
|
||||
|
||||
.card-head i {
|
||||
|
||||
color:#d4af37;
|
||||
color: var(--theme-yellow);
|
||||
margin-right: 10px;
|
||||
|
||||
}
|
||||
|
||||
.card-body {
|
||||
|
||||
padding: 22px;
|
||||
|
||||
}
|
||||
|
||||
.card-body ul {
|
||||
|
||||
padding-left: 20px;
|
||||
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.card-body li {
|
||||
|
||||
margin-bottom: 10px;
|
||||
color:#555;
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
.card-body li:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/*==========================
|
||||
Alert
|
||||
Notice Alert Box
|
||||
===========================*/
|
||||
|
||||
.notice {
|
||||
|
||||
background:#fff7e4;
|
||||
border-left:6px solid #d4af37;
|
||||
background: rgba(255, 234, 133, 0.2);
|
||||
border-left: 5px solid var(--theme-red);
|
||||
border-radius: 16px;
|
||||
padding: 22px;
|
||||
margin-top: 35px;
|
||||
box-shadow:0 8px 25px rgba(0,0,0,.06);
|
||||
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, .03);
|
||||
}
|
||||
|
||||
.notice h5 {
|
||||
|
||||
color:#5E244E;
|
||||
color: var(--theme-navy);
|
||||
font-weight: 700;
|
||||
|
||||
}
|
||||
|
||||
.notice p {
|
||||
|
||||
margin-bottom: 0;
|
||||
color:#555;
|
||||
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
/*==========================
|
||||
Contact
|
||||
Contact Box
|
||||
===========================*/
|
||||
|
||||
.contact-card {
|
||||
|
||||
margin-top:35px;
|
||||
border-radius:20px;
|
||||
background:#4a1c3e;
|
||||
color:#fff;
|
||||
margin-top: 30px;
|
||||
border-radius: 16px;
|
||||
background: linear-gradient(135deg, #2B293F 0%, #94A6F959 100%) !important;
|
||||
color: var(--white);
|
||||
padding: 35px;
|
||||
box-shadow:0 12px 35px rgba(0,0,0,.12);
|
||||
|
||||
box-shadow: 0 8px 25px rgba(31, 37, 65, 0.15);
|
||||
}
|
||||
|
||||
.contact-card h4 {
|
||||
|
||||
color:#d4af37;
|
||||
color: var(--theme-yellow);
|
||||
font-weight: 700;
|
||||
|
||||
}
|
||||
|
||||
.contact-item {
|
||||
|
||||
margin-top: 18px;
|
||||
font-size: 15px;
|
||||
|
||||
}
|
||||
|
||||
.contact-item i {
|
||||
|
||||
color:#d4af37;
|
||||
color: var(--theme-yellow);
|
||||
width: 28px;
|
||||
|
||||
}
|
||||
|
||||
@media(max-width:768px) {
|
||||
.guideline-hero, .contact-card {
|
||||
padding: 25px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container py-4">
|
||||
|
||||
<!-- Hero -->
|
||||
|
||||
<div class="guideline-hero">
|
||||
|
||||
<h2>
|
||||
<i class="fas fa-book-open"></i>
|
||||
<i class="fas fa-book-open me-2" style="color: var(--theme-yellow);"></i>
|
||||
Student Guidelines
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
Welcome to the Automobile Engineering Academy. These guidelines are
|
||||
designed to help every student maintain professionalism, safety,
|
||||
discipline, and academic excellence throughout the training programme.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Guidelines Cards -->
|
||||
<div class="row g-4">
|
||||
|
||||
<!-- Classroom -->
|
||||
|
||||
<div class="col-lg-6">
|
||||
|
||||
<div class="guide-card">
|
||||
|
||||
<div class="card-head">
|
||||
|
||||
<h5>
|
||||
<i class="fas fa-chalkboard-teacher"></i>
|
||||
Classroom Rules
|
||||
</h5>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Attend every class on time.</li>
|
||||
|
||||
<li>Maintain discipline and respect lecturers.</li>
|
||||
|
||||
<li>Switch mobile phones to silent mode.</li>
|
||||
|
||||
<li>Complete all assignments before deadlines.</li>
|
||||
|
||||
<li>Keep classrooms clean and organized.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Workshop -->
|
||||
|
||||
<div class="col-lg-6">
|
||||
|
||||
<div class="guide-card">
|
||||
|
||||
<div class="card-head">
|
||||
|
||||
<h5>
|
||||
<i class="fas fa-tools"></i>
|
||||
Workshop Safety
|
||||
</h5>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Wear PPE before entering workshops.</li>
|
||||
|
||||
<li>Follow instructor safety instructions.</li>
|
||||
|
||||
<li>Never operate equipment without permission.</li>
|
||||
|
||||
<li>Report damaged tools immediately.</li>
|
||||
|
||||
<li>Keep workstations clean after practical sessions.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Attendance -->
|
||||
|
||||
<div class="col-lg-6">
|
||||
|
||||
<div class="guide-card">
|
||||
|
||||
<div class="card-head">
|
||||
|
||||
<h5>
|
||||
<i class="fas fa-user-check"></i>
|
||||
Attendance Policy
|
||||
</h5>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Minimum attendance requirement is 80%.</li>
|
||||
|
||||
<li>Medical leave must be supported by documents.</li>
|
||||
|
||||
<li>Repeated absence may affect examinations.</li>
|
||||
|
||||
<li>Late arrivals will be recorded.</li>
|
||||
|
||||
<li>Inform the administration if absent.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Dress -->
|
||||
|
||||
<div class="col-lg-6">
|
||||
|
||||
<div class="guide-card">
|
||||
|
||||
<div class="card-head">
|
||||
|
||||
<h5>
|
||||
<i class="fas fa-user-tie"></i>
|
||||
Uniform & PPE
|
||||
</h5>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Wear academy uniform during lectures.</li>
|
||||
|
||||
<li>Safety shoes are compulsory.</li>
|
||||
|
||||
<li>Use gloves and safety glasses.</li>
|
||||
|
||||
<li>Long hair must be tied properly.</li>
|
||||
|
||||
<li>ID card must be visible at all times.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Assessment -->
|
||||
|
||||
<div class="col-lg-6">
|
||||
|
||||
<div class="guide-card">
|
||||
|
||||
<div class="card-head">
|
||||
|
||||
<h5>
|
||||
<i class="fas fa-file-alt"></i>
|
||||
Assessment Rules
|
||||
</h5>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Submit assignments before due dates.</li>
|
||||
|
||||
<li>No plagiarism is permitted.</li>
|
||||
|
||||
<li>Bring required materials for practical tests.</li>
|
||||
|
||||
<li>Follow examination regulations.</li>
|
||||
|
||||
<li>Maintain academic honesty.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Conduct -->
|
||||
|
||||
<div class="col-lg-6">
|
||||
|
||||
<div class="guide-card">
|
||||
|
||||
<div class="card-head">
|
||||
|
||||
<h5>
|
||||
<i class="fas fa-handshake"></i>
|
||||
Student Conduct
|
||||
</h5>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Respect staff and fellow students.</li>
|
||||
|
||||
<li>Protect academy property.</li>
|
||||
|
||||
<li>Do not smoke inside the campus.</li>
|
||||
|
||||
<li>Avoid discrimination and harassment.</li>
|
||||
|
||||
<li>Represent the academy professionally.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Notice -->
|
||||
|
||||
<div class="notice">
|
||||
|
||||
<h5>
|
||||
<i class="fas fa-exclamation-circle text-warning"></i>
|
||||
<i class="fas fa-exclamation-circle me-1" style="color: var(--theme-red);"></i>
|
||||
Important Notice
|
||||
</h5>
|
||||
|
||||
<p>
|
||||
|
||||
Students who fail to follow academy regulations may face disciplinary
|
||||
action according to the Automobile Engineering Academy Student Policy.
|
||||
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Contact -->
|
||||
|
||||
<div class="contact-card">
|
||||
|
||||
<h4>
|
||||
|
||||
<i class="fas fa-headset"></i>
|
||||
<i class="fas fa-headset me-2"></i>
|
||||
Student Support
|
||||
|
||||
</h4>
|
||||
|
||||
<p class="mt-3">
|
||||
|
||||
<p class="mt-3 text-white-50">
|
||||
If you have any questions regarding academic regulations,
|
||||
attendance, workshop safety, or student services, please contact
|
||||
the Student Affairs Office.
|
||||
|
||||
</p>
|
||||
|
||||
<div class="contact-item">
|
||||
|
||||
<i class="fas fa-envelope"></i>
|
||||
support@academy.lk
|
||||
|
||||
</div>
|
||||
|
||||
<div class="contact-item">
|
||||
|
||||
<i class="fas fa-phone"></i>
|
||||
+94 11 234 5678
|
||||
|
||||
</div>
|
||||
|
||||
<div class="contact-item">
|
||||
|
||||
<i class="fas fa-map-marker-alt"></i>
|
||||
Automobile Engineering Academy
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,186 +6,358 @@
|
|||
|
||||
<style>
|
||||
:root {
|
||||
--primary:#5E244E;
|
||||
--secondary:#8B3A74;
|
||||
--light:#f8f4f7;
|
||||
--primary: #3E51B8; /* Tech Blue */
|
||||
--primary-light: #0a67df; /* Vibrant Electric Blue */
|
||||
--secondary: #BC1A1A; /* Deep Racing Red */
|
||||
--secondary-hover: #822424; /* Dark Burnt Red */
|
||||
--bg-light: #F8FAFC; /* Soft slate light gray */
|
||||
--text-main: #0F172A; /* Slate dark grey */
|
||||
--text-muted: #64748B; /* Neutral gray */
|
||||
--card-border: rgba(226, 232, 240, 0.9);
|
||||
}
|
||||
|
||||
/* ===== HERO SECTION ===== */
|
||||
.hero-about {
|
||||
min-height:60vh;
|
||||
background:
|
||||
linear-gradient(rgba(0,0,0,.7),rgba(0,0,0,.7)),
|
||||
url('https://images.pexels.com/photos/1595385/pexels-photo-1595385.jpeg');
|
||||
position: relative;
|
||||
min-height: 48vh;
|
||||
background: linear-gradient(135deg, rgba(15, 23, 42, 0.88) 0%, rgba(30, 41, 59, 0.82) 50%, rgba(15, 23, 42, 0.92) 100%),
|
||||
url('https://images.unsplash.com/photo-1617814076367-b759c7d7e738?auto=format&fit=crop&w=1600&q=80');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
color:#fff;
|
||||
color: #ffffff;
|
||||
padding: 70px 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.section-title{
|
||||
text-align:center;
|
||||
margin-bottom:40px;
|
||||
.hero-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
border: 1px solid rgba(255, 255, 255, 0.25);
|
||||
backdrop-filter: blur(14px);
|
||||
-webkit-backdrop-filter: blur(14px);
|
||||
color: #FFE618;
|
||||
font-size: 12px;
|
||||
font-weight: 750;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
padding: 7px 18px;
|
||||
border-radius: 999px;
|
||||
margin-bottom: 18px;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.about-box {
|
||||
background:#fff;
|
||||
.hero-about h1 {
|
||||
font-size: clamp(2.3rem, 4vw, 3.6rem);
|
||||
font-weight: 800;
|
||||
line-height: 1.15;
|
||||
letter-spacing: -0.03em;
|
||||
text-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.hero-about p.lead {
|
||||
font-size: clamp(1rem, 1.2vw, 1.25rem);
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
max-width: 700px;
|
||||
margin: 16px auto 0;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* ===== STATS BAR ===== */
|
||||
.stats-container {
|
||||
margin-top: -38px;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.stat-glass-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid rgba(226, 232, 240, 0.9);
|
||||
border-radius: 20px;
|
||||
padding:35px 25px;
|
||||
box-shadow:0 10px 30px rgba(0,0,0,.05);
|
||||
transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||
border: 1px solid #efeff4;
|
||||
padding: 20px 16px;
|
||||
text-align: center;
|
||||
box-shadow: 0 10px 28px rgba(15, 23, 42, 0.06);
|
||||
transition: all 0.35s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
|
||||
.stat-glass-card:hover {
|
||||
transform: translateY(-6px);
|
||||
box-shadow: 0 18px 40px rgba(62, 81, 184, 0.14);
|
||||
border-color: rgba(62, 81, 184, 0.3);
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
background: rgba(62, 81, 184, 0.08);
|
||||
color: var(--primary);
|
||||
border-radius: 12px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 18px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.stat-number {
|
||||
font-size: 26px;
|
||||
font-weight: 800;
|
||||
color: var(--text-main);
|
||||
line-height: 1;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 12.5px;
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* ===== MINIMALIST VISION & MISSION ===== */
|
||||
.minimal-icon-badge {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
border-radius: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
flex-shrink: 0;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.animate-item:hover .minimal-icon-badge {
|
||||
transform: scale(1.1) rotate(4deg);
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.border-start-md {
|
||||
border-left: 1px solid rgba(226, 232, 240, 0.9) !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== FEATURE BOXES ===== */
|
||||
.about-box {
|
||||
position: relative;
|
||||
background: #ffffff;
|
||||
border-radius: 22px;
|
||||
padding: 34px 24px;
|
||||
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.04);
|
||||
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
border: 1px solid rgba(226, 232, 240, 0.9);
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.about-box::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, #3E51B8 0%, #FFE618 50%, #BC1A1A 100%);
|
||||
opacity: 0.35;
|
||||
transition: opacity 0.4s ease;
|
||||
}
|
||||
|
||||
.about-box:hover::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.about-box:hover {
|
||||
transform: translateY(-10px) scale(1.02);
|
||||
box-shadow: 0 20px 40px rgba(94, 36, 78, 0.1);
|
||||
border-color: var(--primary);
|
||||
transform: translateY(-8px);
|
||||
box-shadow: 0 20px 45px -10px rgba(62, 81, 184, 0.14);
|
||||
border-color: rgba(62, 81, 184, 0.3);
|
||||
}
|
||||
|
||||
.icon-circle {
|
||||
width:75px;
|
||||
height:75px;
|
||||
background:var(--primary);
|
||||
color:#fff;
|
||||
border-radius:50%;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
background: linear-gradient(135deg, rgba(62, 81, 184, 0.1) 0%, rgba(10, 103, 223, 0.06) 100%);
|
||||
color: var(--primary);
|
||||
border-radius: 20px;
|
||||
border: 1px solid rgba(62, 81, 184, 0.2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size:28px;
|
||||
margin:auto;
|
||||
transition: all 0.4s ease;
|
||||
font-size: 26px;
|
||||
margin: 0 auto 20px;
|
||||
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
|
||||
.about-box:hover .icon-circle {
|
||||
background: var(--secondary);
|
||||
transform: rotateY(180deg); /* කාඩ් එක උඩට යද්දී අයිකන් එක කැරකෙනවා */
|
||||
background: linear-gradient(135deg, #0F2C59 0%, #3E51B8 100%);
|
||||
color: #ffffff;
|
||||
border-color: transparent;
|
||||
transform: scale(1.12) rotate(6deg);
|
||||
box-shadow: 0 10px 25px rgba(62, 81, 184, 0.35);
|
||||
}
|
||||
|
||||
/* ========================================================
|
||||
Advanced CSS Scroll Animations
|
||||
======================================================== */
|
||||
/* ===== CTA BUTTON ===== */
|
||||
.cta-btn {
|
||||
background: linear-gradient(135deg, #0F2C59 0%, #3E51B8 100%);
|
||||
color: #ffffff !important;
|
||||
padding: 13px 36px;
|
||||
border-radius: 999px;
|
||||
font-weight: 750;
|
||||
font-size: 14.5px;
|
||||
text-decoration: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
transition: all 0.35s ease;
|
||||
box-shadow: 0 8px 24px rgba(62, 81, 184, 0.25);
|
||||
}
|
||||
|
||||
.cta-btn:hover {
|
||||
background: linear-gradient(135deg, #BC1A1A 0%, #822424 100%);
|
||||
transform: translateY(-3px) scale(1.02);
|
||||
box-shadow: 0 12px 30px rgba(188, 26, 26, 0.35);
|
||||
}
|
||||
|
||||
.cta-btn i {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.cta-btn:hover i {
|
||||
transform: translateX(6px);
|
||||
}
|
||||
|
||||
/* ===== SCROLL ANIMATIONS ===== */
|
||||
.animate-item {
|
||||
opacity: 0;
|
||||
will-change: transform, opacity;
|
||||
transition: all 0.8s cubic-bezier(0.25, 1, 0.5, 1);
|
||||
}
|
||||
|
||||
/* 1. පල්ලෙහා ඉඳන් උඩට එන ඇනිමේෂන් */
|
||||
.fade-up-init {
|
||||
transform: translateY(40px);
|
||||
}
|
||||
.fade-up-init { transform: translateY(30px); }
|
||||
.slide-left-init { transform: translateX(-40px); }
|
||||
.slide-right-init { transform: translateX(40px); }
|
||||
.zoom-in-init { transform: scale(0.94); }
|
||||
|
||||
/* 2. වමේ ඉඳන් දකුණට (රූපය සඳහා) */
|
||||
.slide-left-init {
|
||||
transform: translateX(-50px);
|
||||
}
|
||||
|
||||
/* 3. දකුණේ ඉඳන් වමට (විස්තරය සඳහා) */
|
||||
.slide-right-init {
|
||||
transform: translateX(50px);
|
||||
}
|
||||
|
||||
/* 4. Zoom වෙලා bounce වෙන්න (කාඩ්ස් සඳහා) */
|
||||
.zoom-in-init {
|
||||
transform: scale(0.85);
|
||||
}
|
||||
|
||||
/* Active Class (Scroll කරද්දී apply වේ) */
|
||||
.animate-item.animated {
|
||||
opacity: 1;
|
||||
transform: translate(0) scale(1);
|
||||
}
|
||||
|
||||
/* CTA බටන් එක ගැස්සෙන ඇනිමේෂන් එකක් */
|
||||
@keyframes pulse-btn {
|
||||
0% { box-shadow: 0 0 0 0 rgba(94, 36, 78, 0.4); }
|
||||
70% { box-shadow: 0 0 0 15px rgba(94, 36, 78, 0); }
|
||||
100% { box-shadow: 0 0 0 0 rgba(94, 36, 78, 0); }
|
||||
}
|
||||
|
||||
.cta-btn {
|
||||
background: var(--primary);
|
||||
color: #fff !important;
|
||||
padding: 14px 35px;
|
||||
border-radius: 50px;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
transition: 0.3s;
|
||||
animation: pulse-btn 2s infinite;
|
||||
}
|
||||
|
||||
.cta-btn:hover {
|
||||
background: var(--secondary);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- HERO -->
|
||||
<!-- HERO SECTION -->
|
||||
<section class="hero-about">
|
||||
<div class="container">
|
||||
<div class="animate-item animated fade-up-init">
|
||||
<h1 class="fw-bold display-4">About Our Institute</h1>
|
||||
<p class="mt-3 lead" style="max-width: 700px; margin: auto;">
|
||||
We are committed to delivering high-quality automotive education
|
||||
with practical training and industry-focused learning.
|
||||
<span class="hero-badge"><i class="fa-solid fa-graduation-cap"></i> Pioneering Automotive Academy</span>
|
||||
<h1 class="fw-bold">Empowering Future Mobility Leaders</h1>
|
||||
<p class="lead">
|
||||
We are committed to delivering world-class automotive engineering education with hands-on workshop mastery, TVEC accredited qualifications, and cutting-edge EV technology training.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ABOUT CONTENT -->
|
||||
<section class="py-5 overflow-hidden">
|
||||
<div class="container">
|
||||
<div class="row align-items-center g-5">
|
||||
<!-- වමේ සිට දකුණට පැමිණේ -->
|
||||
<!-- FLOATING STATS COUNTER -->
|
||||
<div class="container stats-container">
|
||||
<div class="row g-3 justify-content-center">
|
||||
<div class="col-6 col-md-3 animate-item zoom-in-init" style="transition-delay: 100ms;">
|
||||
<div class="stat-glass-card">
|
||||
<div class="stat-icon"><i class="fa-solid fa-user-graduate"></i></div>
|
||||
<div class="stat-number count-up" data-count-target="2500" data-count-suffix="+">0+</div>
|
||||
<div class="stat-label">Graduated Technicians</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-3 animate-item zoom-in-init" style="transition-delay: 200ms;">
|
||||
<div class="stat-glass-card">
|
||||
<div class="stat-icon"><i class="fa-solid fa-screwdriver-wrench"></i></div>
|
||||
<div class="stat-number">100%</div>
|
||||
<div class="stat-label">Practical Lab Mastery</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-3 animate-item zoom-in-init" style="transition-delay: 300ms;">
|
||||
<div class="stat-glass-card">
|
||||
<div class="stat-icon"><i class="fa-solid fa-award"></i></div>
|
||||
<div class="stat-number">15+</div>
|
||||
<div class="stat-label">Years of Excellence</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-md-3 animate-item zoom-in-init" style="transition-delay: 400ms;">
|
||||
<div class="stat-glass-card">
|
||||
<div class="stat-icon"><i class="fa-solid fa-briefcase"></i></div>
|
||||
<div class="stat-number">95%</div>
|
||||
<div class="stat-label">Job Placement Rate</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- VISION & MISSION MINIMALIST 1-ROW SECTION -->
|
||||
<section class="py-5 bg-white">
|
||||
<div class="container py-3">
|
||||
<div class="row g-4 align-items-stretch">
|
||||
|
||||
<!-- VISION (LEFT COLUMN) -->
|
||||
<div class="col-md-6 animate-item slide-left-init">
|
||||
<img src="https://images.pexels.com/photos/3862130/pexels-photo-3862130.jpeg"
|
||||
class="img-fluid rounded shadow-lg"
|
||||
alt="About Image">
|
||||
<div class="p-4 rounded-4 bg-light border border-light-subtle h-100">
|
||||
<div class="d-flex align-items-center gap-3 mb-3">
|
||||
<div class="minimal-icon-badge bg-primary-subtle text-primary">
|
||||
<i class="fa-solid fa-lightbulb"></i>
|
||||
</div>
|
||||
<div>
|
||||
<span class="badge bg-primary-subtle text-primary fw-bold text-uppercase px-2 py-1 rounded-2 small mb-1" style="font-size: 11px;">GLOBAL GOAL</span>
|
||||
<h3 class="fw-bold text-dark mb-0 fs-4">Our Vision</h3>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-secondary fs-6 lh-base mb-0">
|
||||
To be a global leader in automotive education, driving the future of mobility by empowering the next generation of engineers, technicians, and EV innovators.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- දකුණේ සිට වමට පැමිණේ -->
|
||||
<!-- MISSION (RIGHT COLUMN) -->
|
||||
<div class="col-md-6 animate-item slide-right-init">
|
||||
<h2 class="fw-bold mb-3">Who We Are</h2>
|
||||
<p class="text-muted fs-5">
|
||||
Our institute specializes in automotive engineering education,
|
||||
offering hands-on training in modern vehicle technologies,
|
||||
mechanical systems, and electric vehicles.
|
||||
</p>
|
||||
<p class="text-muted mb-4">
|
||||
We focus on building skilled professionals who are ready for
|
||||
the global automotive industry.
|
||||
</p>
|
||||
<a href="{{ route('courses') }}" class="btn btn-dark btn-lg px-4 rounded-pill">
|
||||
View Courses
|
||||
</a>
|
||||
<div class="p-4 rounded-4 bg-light border border-light-subtle h-100">
|
||||
<div class="d-flex align-items-center gap-3 mb-3">
|
||||
<div class="minimal-icon-badge bg-danger-subtle text-danger">
|
||||
<i class="fa-solid fa-bullseye"></i>
|
||||
</div>
|
||||
<div>
|
||||
<span class="badge bg-danger-subtle text-danger fw-bold text-uppercase px-2 py-1 rounded-2 small mb-1" style="font-size: 11px;">CORE PURPOSE</span>
|
||||
<h3 class="fw-bold text-dark mb-0 fs-4">Our Mission</h3>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-secondary fs-6 lh-base mb-0">
|
||||
To foster technical mastery and critical thinking through immersive, practical learning environments, strong industry partnerships, and a commitment to eco-friendly automotive practices.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- FEATURES -->
|
||||
<section class="py-5 bg-light">
|
||||
<div class="container">
|
||||
|
||||
<div class="section-title animate-item fade-up-init">
|
||||
<h2 class="fw-bold">Why Choose Us</h2>
|
||||
<p class="text-muted">We provide the best learning experience</p>
|
||||
<!-- ADVANTAGES / WHY CHOOSE US -->
|
||||
<section class="py-5 bg-light position-relative">
|
||||
<div class="container py-4">
|
||||
<div class="text-center mb-5 animate-item fade-up-init">
|
||||
<span class="text-uppercase fw-bold small text-primary letter-spacing-1"><i class="fa-solid fa-award me-1"></i> Core Advantage</span>
|
||||
<h2 class="display-6 fw-bold text-dark mt-2">Why Study With AutoEdu?</h2>
|
||||
<p class="text-muted fs-5 max-width-600 mx-auto">We combine academic excellence with real-world workshop diagnostic training.</p>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
<!-- කාඩ් එකින් එක Zoom-in වේ -->
|
||||
<div class="col-md-4 animate-item zoom-in-init" style="transition-delay: 100ms;">
|
||||
<div class="about-box text-center">
|
||||
<div class="icon-circle">
|
||||
<i class="fa-solid fa-chalkboard-user"></i>
|
||||
</div>
|
||||
<h4 class="mt-4 fw-bold">Expert Lecturers</h4>
|
||||
<p class="text-muted mb-0">
|
||||
Experienced industry professionals guiding your learning journey.
|
||||
<h4 class="fw-bold text-dark mb-3">Expert Lecturers</h4>
|
||||
<p class="text-muted mb-0 lh-base">
|
||||
Learn directly from veteran automotive engineers, diagnostic specialists, and TVEC certified master instructors.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -195,9 +367,9 @@
|
|||
<div class="icon-circle">
|
||||
<i class="fa-solid fa-screwdriver-wrench"></i>
|
||||
</div>
|
||||
<h4 class="mt-4 fw-bold">Practical Training</h4>
|
||||
<p class="text-muted mb-0">
|
||||
Hands-on workshop experience with real vehicles and tools.
|
||||
<h4 class="fw-bold text-dark mb-3">Practical Training</h4>
|
||||
<p class="text-muted mb-0 lh-base">
|
||||
Hands-on workshop experience working on modern EFI engines, EV battery test bays, and automated gearboxes.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -207,36 +379,38 @@
|
|||
<div class="icon-circle">
|
||||
<i class="fa-solid fa-certificate"></i>
|
||||
</div>
|
||||
<h4 class="mt-4 fw-bold">Certified Courses</h4>
|
||||
<p class="text-muted mb-0">
|
||||
Industry-recognized certifications to boost your career.
|
||||
<h4 class="fw-bold text-dark mb-3">Certified Qualifications</h4>
|
||||
<p class="text-muted mb-0 lh-base">
|
||||
Earn internationally recognized NVQ Level 4/5 diplomas and certifications that accelerate your global career.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA -->
|
||||
<section class="py-5 text-center bg-white overflow-hidden">
|
||||
<!-- CALL TO ACTION (CTA) -->
|
||||
<section class="py-5 text-center bg-white overflow-hidden position-relative">
|
||||
<div class="container py-4 animate-item fade-up-init">
|
||||
<h2 class="fw-bold mb-3">Start Your Automotive Career Today</h2>
|
||||
<p class="text-muted fs-5 mb-5">
|
||||
Join our institute and become a skilled automotive professional.
|
||||
<div class="p-5 rounded-4 shadow-sm position-relative overflow-hidden" style="background: linear-gradient(135deg, #0F172A 0%, #1E293B 100%);">
|
||||
<span class="badge bg-warning text-dark font-monospace mb-3 px-3 py-2 rounded-pill"><i class="fa-solid fa-bolt me-1"></i> ADMISSIONS OPEN 2026</span>
|
||||
<h2 class="display-6 fw-bold text-white mb-3">Start Your Automotive Career Today</h2>
|
||||
<p class="text-white-50 fs-5 mb-4 max-width-600 mx-auto">
|
||||
Take the first step toward becoming a certified automotive engineer or high-voltage EV specialist.
|
||||
</p>
|
||||
<div class="d-flex justify-content-center">
|
||||
<a href="/apply" class="cta-btn shadow">
|
||||
Apply Courses
|
||||
<a href="/apply" class="cta-btn">
|
||||
Apply For Courses <i class="fa-solid fa-arrow-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Scroll animations observer
|
||||
const animatedElements = document.querySelectorAll('.animate-item');
|
||||
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
|
|
@ -245,10 +419,35 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||
}
|
||||
});
|
||||
}, {
|
||||
threshold: 0.15 // Element එකෙන් 15%ක් පෙනෙද්දීම ඇනිමේෂන් එක පටන් ගනී
|
||||
threshold: 0.15
|
||||
});
|
||||
|
||||
animatedElements.forEach(el => observer.observe(el));
|
||||
|
||||
// Stats Number Counter Animation
|
||||
const counterElements = document.querySelectorAll('.count-up');
|
||||
const counterObserver = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
const el = entry.target;
|
||||
const target = parseInt(el.getAttribute('data-count-target') || '0', 10);
|
||||
const suffix = el.getAttribute('data-count-suffix') || '';
|
||||
let current = 0;
|
||||
const increment = Math.ceil(target / 40);
|
||||
const timer = setInterval(() => {
|
||||
current += increment;
|
||||
if (current >= target) {
|
||||
current = target;
|
||||
clearInterval(timer);
|
||||
}
|
||||
el.textContent = current.toLocaleString() + suffix;
|
||||
}, 30);
|
||||
counterObserver.unobserve(el);
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.5 });
|
||||
|
||||
counterElements.forEach(el => counterObserver.observe(el));
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,672 @@
|
|||
@extends('layouts.adminnav')
|
||||
|
||||
@section('title', 'Admin Dashboard')
|
||||
|
||||
@section('content')
|
||||
<style>
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
.welcome-card {
|
||||
background: linear-gradient(135deg, #1e293b 0%, #334155 100%);
|
||||
color: #ffffff;
|
||||
border-radius: 12px;
|
||||
}
|
||||
.stat-card {
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
}
|
||||
.stat-card:hover {
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
.icon-box {
|
||||
width: 55px;
|
||||
height: 55px;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24px;
|
||||
}
|
||||
/* Edit Mode Control Styles */
|
||||
/* Edit Mode Control Styles */
|
||||
.edit-only {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Display rule based on element types */
|
||||
.is-editing .edit-only {
|
||||
display: inline-block !important;
|
||||
}
|
||||
.is-editing div.edit-only {
|
||||
display: block !important;
|
||||
}
|
||||
.is-editing td.edit-only,
|
||||
.is-editing th.edit-only {
|
||||
display: table-cell !important;
|
||||
}
|
||||
.is-editing .d-flex.edit-only {
|
||||
display: flex !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container-fluid py-4" id="dashboardWrapper">
|
||||
|
||||
<!-- Welcome Banner & Pin Unlock Header -->
|
||||
<div class="welcome-card p-4 mb-4 shadow-sm d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h3 class="fw-bold mb-1"><i class="fa-solid fa-gauge me-2"></i>Welcome to Admin Dashboard</h3>
|
||||
<p class="mb-0 text-white-50">Automobile Engineering Academy System Overview</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Alert Messages -->
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible fade show mb-4" role="alert">
|
||||
<i class="fa-solid fa-circle-check me-2"></i>{{ session('success') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(session('error'))
|
||||
<div class="alert alert-danger alert-dismissible fade show mb-4" role="alert">
|
||||
<i class="fa-solid fa-triangle-exclamation me-2"></i>{{ session('error') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Quick Stats Cards Row -->
|
||||
<div class="row g-4 mb-4">
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="card stat-card shadow-sm h-100">
|
||||
<div class="card-body d-flex align-items-center justify-content-between p-4">
|
||||
<div>
|
||||
<span class="text-muted fw-bold small text-uppercase">My Courses</span>
|
||||
<h3 class="fw-bold text-dark mt-1 mb-0">Manage</h3>
|
||||
</div>
|
||||
<div class="icon-box bg-primary bg-opacity-10 text-primary">
|
||||
<i class="fa-solid fa-book"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-light border-0 py-2 text-center">
|
||||
<a href="{{ route('admin.mycourses') }}" class="text-primary fw-bold text-decoration-none small">
|
||||
View Details <i class="fa-solid fa-arrow-right ms-1"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="card stat-card shadow-sm h-100">
|
||||
<div class="card-body d-flex align-items-center justify-content-between p-4">
|
||||
<div>
|
||||
<span class="text-muted fw-bold small text-uppercase">Active Slots</span>
|
||||
<h3 class="fw-bold text-dark mt-1 mb-0">{{ $totalTimetableSlots ?? 0 }}</h3>
|
||||
</div>
|
||||
<div class="icon-box bg-success bg-opacity-10 text-success">
|
||||
<i class="fa-solid fa-calendar-days"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-light border-0 py-2 text-center">
|
||||
<a href="{{ route('admin.timetable') }}" class="text-success fw-bold text-decoration-none small">
|
||||
Manage Timetable <i class="fa-solid fa-arrow-right ms-1"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="card stat-card shadow-sm h-100">
|
||||
<div class="card-body d-flex align-items-center justify-content-between p-4">
|
||||
<div>
|
||||
<span class="text-muted fw-bold small text-uppercase">Results</span>
|
||||
<h3 class="fw-bold text-dark mt-1 mb-0">Publish</h3>
|
||||
</div>
|
||||
<div class="icon-box bg-warning bg-opacity-10 text-warning">
|
||||
<i class="fa-solid fa-graduation-cap"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-light border-0 py-2 text-center">
|
||||
<a href="{{ route('admin.results') }}" class="text-warning fw-bold text-decoration-none small">
|
||||
Manage Results <i class="fa-solid fa-arrow-right ms-1"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="card stat-card shadow-sm h-100">
|
||||
<div class="card-body d-flex align-items-center justify-content-between p-4">
|
||||
<div>
|
||||
<span class="text-muted fw-bold small text-uppercase">Notifications</span>
|
||||
<h3 class="fw-bold text-dark mt-1 mb-0">{{ $unreadNotifications ?? 0 }} New</h3>
|
||||
</div>
|
||||
<div class="icon-box bg-danger bg-opacity-10 text-danger">
|
||||
<i class="fa-solid fa-bell"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-light border-0 py-2 text-center">
|
||||
<a href="#notifications-section" class="text-danger fw-bold text-decoration-none small">
|
||||
View All <i class="fa-solid fa-arrow-down ms-1"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content Area -->
|
||||
<div class="row g-4 mb-4">
|
||||
<div class="col-lg-7">
|
||||
<div class="card border-0 shadow-sm rounded-3 h-100">
|
||||
<div class="card-header bg-white py-3 border-0">
|
||||
<h5 class="fw-bold mb-0 text-dark">
|
||||
<i class="fa-solid fa-bolt text-warning me-2"></i>Quick Management Shortcuts
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<a href="{{ route('admin.timetable') }}" class="btn btn-outline-primary p-3 w-100 text-start d-flex align-items-center rounded-3">
|
||||
<i class="fa-solid fa-calendar-plus fs-3 me-3"></i>
|
||||
<div>
|
||||
<strong class="d-block">Manage Timetable</strong>
|
||||
<small class="text-muted">Edit weekly schedules and subjects</small>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<a href="{{ route('admin.mycourses') }}" class="btn btn-outline-success p-3 w-100 text-start d-flex align-items-center rounded-3">
|
||||
<i class="fa-solid fa-folder-plus fs-3 me-3"></i>
|
||||
<div>
|
||||
<strong class="d-block">Courses & Modules</strong>
|
||||
<small class="text-muted">Add or edit active modules</small>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<a href="{{ route('admin.results') }}" class="btn btn-outline-warning p-3 w-100 text-start d-flex align-items-center rounded-3">
|
||||
<i class="fa-solid fa-file-invoice fs-3 me-3"></i>
|
||||
<div>
|
||||
<strong class="d-block">Student Results</strong>
|
||||
<small class="text-muted">Upload and update grades</small>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<a href="{{ route('admin.profile') }}" class="btn btn-outline-danger p-3 w-100 text-start d-flex align-items-center rounded-3">
|
||||
<i class="fa-solid fa-user-gear fs-3 me-3"></i>
|
||||
<div>
|
||||
<strong class="d-block">Account Settings</strong>
|
||||
<small class="text-muted">Update profile and password</small>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- System Notifications Column -->
|
||||
<div class="col-lg-5" id="notifications-section">
|
||||
<div class="card border-0 shadow-sm rounded-3 h-100">
|
||||
<div class="card-header bg-white py-3 border-0 d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h5 class="fw-bold mb-0 text-dark d-inline me-2">
|
||||
<i class="fa-solid fa-bell text-danger me-2"></i>System Notifications
|
||||
</h5>
|
||||
<span class="badge bg-danger rounded-pill">{{ $unreadNotifications ?? 0 }} Unread</span>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-primary rounded-3" data-bs-toggle="modal" data-bs-target="#addNotificationModal">
|
||||
<i class="fa-solid fa-plus me-1"></i> Add
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-0" style="max-height: 450px; overflow-y: auto;">
|
||||
<ul class="list-group list-group-flush">
|
||||
@forelse($notifications ?? [] as $notification)
|
||||
<li class="list-group-item p-3 border-bottom {{ $notification->is_read ? 'bg-light text-muted' : 'bg-white' }}">
|
||||
<div class="d-flex justify-content-between align-items-start gap-2">
|
||||
<div class="me-2">
|
||||
@if($notification->type == 'success')
|
||||
<span class="badge bg-success mb-1">Success</span>
|
||||
@elseif($notification->type == 'warning')
|
||||
<span class="badge bg-warning text-dark mb-1">Warning</span>
|
||||
@else
|
||||
<span class="badge bg-info text-dark mb-1">Info</span>
|
||||
@endif
|
||||
|
||||
<h6 class="fw-bold mb-1 {{ $notification->is_read ? 'text-secondary' : 'text-dark' }}">
|
||||
{{ $notification->title }}
|
||||
</h6>
|
||||
<p class="mb-1 text-muted small text-break">{{ $notification->message }}</p>
|
||||
|
||||
<small class="text-secondary opacity-75 d-block" style="font-size: 11px;">
|
||||
<i class="fa-regular fa-clock me-1"></i>{{ $notification->created_at ? $notification->created_at->diffForHumans() : '' }}
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-1 align-items-center flex-shrink-0">
|
||||
@if(!$notification->is_read)
|
||||
<form action="{{ route('admin.notifications.read', $notification->id) }}" method="POST" class="d-inline">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-sm btn-outline-success border-0 rounded-circle" title="Mark as Read">
|
||||
<i class="fa-solid fa-check"></i>
|
||||
</button>
|
||||
</form>
|
||||
@else
|
||||
<span class="text-muted px-1" title="Read"><i class="fa-solid fa-check-double text-secondary"></i></span>
|
||||
@endif
|
||||
|
||||
<button class="btn btn-sm btn-outline-primary border-0 rounded-circle" data-bs-toggle="modal" data-bs-target="#editNotificationModal{{ $notification->id }}" title="Edit">
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
</button>
|
||||
|
||||
<form action="{{ route('admin.notifications.destroy', $notification->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this notification?');">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="btn btn-sm btn-outline-danger border-0 rounded-circle" title="Delete">
|
||||
<i class="fa-solid fa-trash-can"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- Modal: Edit Notification -->
|
||||
<div class="modal fade" id="editNotificationModal{{ $notification->id }}" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header bg-primary text-white">
|
||||
<h5 class="modal-title fw-bold"><i class="fa-solid fa-pen-to-square me-2"></i>Edit Notification</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form action="{{ route('admin.notifications.update', $notification->id) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
<div class="modal-body p-4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Notification Type</label>
|
||||
<select name="type" class="form-select" required>
|
||||
<option value="info" {{ $notification->type == 'info' ? 'selected' : '' }}>Info</option>
|
||||
<option value="success" {{ $notification->type == 'success' ? 'selected' : '' }}>Success</option>
|
||||
<option value="warning" {{ $notification->type == 'warning' ? 'selected' : '' }}>Warning</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Title</label>
|
||||
<input type="text" name="title" class="form-control" value="{{ $notification->title }}" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Message</label>
|
||||
<textarea name="message" class="form-control" rows="3" required>{{ $notification->message }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary"><i class="fa-solid fa-save me-1"></i> Update</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<li class="list-group-item text-center py-4 text-muted">
|
||||
<i class="fa-solid fa-inbox fs-3 d-block mb-2 text-secondary"></i>
|
||||
No notifications found.
|
||||
</li>
|
||||
@endforelse
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal: Add New Notification -->
|
||||
<div class="modal fade" id="addNotificationModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header bg-primary text-white">
|
||||
<h5 class="modal-title fw-bold"><i class="fa-solid fa-bell me-2"></i>Add New Notification</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form action="{{ route('admin.notifications.store') }}" method="POST">
|
||||
@csrf
|
||||
<div class="modal-body p-4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Notification Type</label>
|
||||
<select name="type" class="form-select" required>
|
||||
<option value="info">Info</option>
|
||||
<option value="success">Success</option>
|
||||
<option value="warning">Warning</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Title</label>
|
||||
<input type="text" name="title" class="form-control" placeholder="Enter title" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Message</label>
|
||||
<textarea name="message" class="form-control" rows="3" placeholder="Enter notification content" required></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary"><i class="fa-solid fa-plus me-1"></i> Save Notification</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Registered Users Table -->
|
||||
<div class="row g-4 mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card border-0 shadow-sm rounded-3">
|
||||
<div class="card-header bg-white py-3 border-0 d-flex justify-content-between align-items-center">
|
||||
<h5 class="fw-bold mb-0 text-dark">
|
||||
<i class="fa-solid fa-users text-primary me-2"></i>Registered System Users List
|
||||
</h5>
|
||||
<span class="badge bg-primary rounded-pill">{{ count($users ?? []) }} Users</span>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th class="ps-3">ID</th>
|
||||
<th>Name</th>
|
||||
<th>Email</th>
|
||||
<th>Phone</th>
|
||||
<th>Created Date</th>
|
||||
<th class="text-end pe-3">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($users ?? [] as $user)
|
||||
<tr>
|
||||
<td class="ps-3 fw-bold">#{{ $user->id }}</td>
|
||||
<td>{{ $user->first_name }} {{ $user->last_name }}</td>
|
||||
<td>{{ $user->email }}</td>
|
||||
<td>{{ $user->phone ?? 'N/A' }}</td>
|
||||
<td>{{ $user->created_at ? $user->created_at->format('Y-m-d H:i') : 'N/A' }}</td>
|
||||
|
||||
<td class="text-end pe-3">
|
||||
<form action="{{ route('admin.portallogs.send', $user->id) }}" method="POST" class="d-inline">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-sm btn-primary rounded-2">
|
||||
<i class="fa-solid fa-paper-plane me-1"></i> Send to Portal Log
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="6" class="text-center py-4 text-muted">
|
||||
<i class="fa-solid fa-user-slash fs-3 d-block mb-2 text-secondary"></i>
|
||||
No registered users found.
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- Student Portal Active Logs Table (PIN, Add, Edit & Delete) -->
|
||||
<div class="row g-4" id="portal-logs-section">
|
||||
<div class="col-12">
|
||||
<div class="card border-0 shadow-sm rounded-3">
|
||||
<div class="card-header bg-white py-3 border-0 d-flex justify-content-between align-items-center">
|
||||
<h5 class="fw-bold mb-0 text-dark">
|
||||
<i class="fa-solid fa-address-card text-success me-2"></i>Student Portal Active Logs
|
||||
</h5>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<span class="badge bg-success rounded-pill">{{ count($portalLogs ?? []) }} Active Student Logs</span>
|
||||
|
||||
<button class="btn btn-sm btn-success rounded-3 edit-only" data-bs-toggle="modal" data-bs-target="#addPortalLogModal">
|
||||
<i class="fa-solid fa-plus me-1"></i> Add Portal Log
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th class="ps-3">Log ID</th>
|
||||
<th>User ID</th>
|
||||
<th>Student Name</th>
|
||||
<th>Email</th>
|
||||
<th>Phone</th>
|
||||
<th class="text-center">Portal PIN</th>
|
||||
<th>Created Date</th>
|
||||
<th class="text-end pe-3">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($portalLogs ?? [] as $log)
|
||||
<tr>
|
||||
<td class="ps-3 fw-bold">#LOG-{{ $log->id }}</td>
|
||||
<td>#{{ $log->user_id }}</td>
|
||||
<td>
|
||||
<div class="fw-bold text-dark">
|
||||
@if(!empty($log->first_name) || !empty($log->last_name))
|
||||
{{ trim($log->first_name . ' ' . $log->last_name) }}
|
||||
@elseif($log->user)
|
||||
{{ $log->user->name ?? trim($log->user->first_name . ' ' . $log->user->last_name) }}
|
||||
@else
|
||||
<span class="text-muted">N/A</span>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ $log->email }}</td>
|
||||
<td>{{ $log->phone ?? ($log->user->phone ?? 'N/A') }}</td>
|
||||
|
||||
<!-- Portal PIN Column -->
|
||||
<td class="text-center">
|
||||
<div class="d-flex align-items-center justify-content-center gap-2">
|
||||
|
||||
@if(!empty($log->pin) && $log->pin !== 'N/A')
|
||||
<!-- Current PIN Badge -->
|
||||
<span class="badge bg-dark font-monospace fs-6 px-3 py-2 shadow-sm">
|
||||
<i class="fa-solid fa-key text-warning me-1"></i>{{ $log->pin }}
|
||||
</span>
|
||||
|
||||
<!-- Edit PIN Button (Triggers Modal) -->
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-outline-primary border-0 rounded-circle"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#editPinModal{{ $log->id }}"
|
||||
title="Edit PIN">
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
</button>
|
||||
|
||||
<!-- Delete PIN Form -->
|
||||
<form action="{{ route('admin.portallogs.update', $log->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this PIN?');">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
<input type="hidden" name="pin" value="">
|
||||
<button type="submit" class="btn btn-sm btn-outline-danger border-0 rounded-circle" title="Delete PIN">
|
||||
<i class="fa-solid fa-trash-can"></i>
|
||||
</button>
|
||||
</form>
|
||||
@else
|
||||
<!-- N/A Badge -->
|
||||
<span class="badge bg-secondary font-monospace fs-6 px-3 py-2 opacity-75">
|
||||
<i class="fa-solid fa-key text-white-50 me-1"></i>N/A
|
||||
</span>
|
||||
|
||||
<!-- Add New PIN Button (Triggers Modal) -->
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-success rounded-pill px-2 py-1"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#editPinModal{{ $log->id }}">
|
||||
<i class="fa-solid fa-plus me-1"></i>Add PIN
|
||||
</button>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Edit/Add PIN Bootstrap Modal -->
|
||||
<div class="modal fade" id="editPinModal{{ $log->id }}" tabindex="-1" aria-labelledby="editPinModalLabel{{ $log->id }}" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content text-start">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title fw-bold" id="editPinModalLabel{{ $log->id }}">
|
||||
<i class="fa-solid fa-key text-warning me-2"></i>Edit Portal PIN
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<form action="{{ route('admin.portallogs.update', $log->id) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
<div class="modal-body p-4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Student Name</label>
|
||||
<input type="text" class="form-control" value="{{ trim(($log->first_name ?? '') . ' ' . ($log->last_name ?? '')) }}" disabled>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Portal PIN</label>
|
||||
<input type="text" name="pin" class="form-control" value="{{ $log->pin }}" placeholder="Enter new PIN" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary"><i class="fa-solid fa-save me-1"></i> Save PIN</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td>{{ $log->created_at ? $log->created_at->format('Y-m-d H:i') : 'N/A' }}</td>
|
||||
|
||||
<td class="text-end pe-3">
|
||||
@if($user->is_active)
|
||||
|
||||
<form action="{{ route('admin.portallogs.send', $user->id) }}" method="POST" class="inline" onsubmit="return confirm('Are you sure you want to send this record to Student Portal?');">
|
||||
@csrf
|
||||
<button type="submit" class="portal" style="background-color: #7e3c37; border-color: #e6e939;">
|
||||
<i class="fa-solid fa-paper-plane me-1"></i> Send to Portal Log
|
||||
</button>
|
||||
</form>
|
||||
@else
|
||||
|
||||
<form action="{{ route('admin.portallogs.destroy', $log->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to remove this record from Student Portal? (User account will remain safe)');">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="btn btn-danger btn-sm">
|
||||
<i class="fa-solid fa-trash me-1"></i> Delete Student Log
|
||||
</button>
|
||||
</form>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Edit Portal Log Modal -->
|
||||
<div class="modal fade" id="editPortalLogModal{{ $log->id }}" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header bg-primary text-white">
|
||||
<h5 class="modal-title fw-bold"><i class="fa-solid fa-key me-2"></i>Edit Portal Log & PIN</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form action="{{ route('admin.portallogs.update', $log->id) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
<div class="modal-body p-4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Student Name</label>
|
||||
<input type="text" class="form-control" value="{{ trim($log->first_name . ' ' . $log->last_name) }}" readonly disabled>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Email Address</label>
|
||||
<input type="email" name="email" class="form-control" value="{{ $log->email }}" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Phone Number</label>
|
||||
<input type="text" name="phone" class="form-control" value="{{ $log->phone }}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold text-primary"><i class="fa-solid fa-lock me-1"></i> Student Portal PIN</label>
|
||||
<input type="text" name="pin" class="form-control fw-bold fs-5 text-center text-primary" maxlength="6" value="{{ $log->pin }}" placeholder="Enter PIN (e.g. 1234)" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary"><i class="fa-solid fa-save me-1"></i> Save Changes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="8" class="text-center py-4 text-muted">
|
||||
<i class="fa-solid fa-folder-open fs-3 d-block mb-2 text-secondary"></i>
|
||||
No active student portal logs found.
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Add New Portal Log Modal -->
|
||||
<div class="modal fade" id="addPortalLogModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header bg-success text-white">
|
||||
<h5 class="modal-title fw-bold"><i class="fa-solid fa-user-plus me-2"></i>Add Student Portal Access</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form action="{{ route('admin.portallogs.store') }}" method="POST">
|
||||
@csrf
|
||||
<div class="modal-body p-4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Select User / Student</label>
|
||||
<select name="user_id" class="form-select" required>
|
||||
<option value="">-- Choose System User --</option>
|
||||
@foreach($users ?? [] as $u)
|
||||
<option value="{{ $u->id }}">{{ $u->first_name }} {{ $u->last_name }} ({{ $u->email }})</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Email Address</label>
|
||||
<input type="email" name="email" class="form-control" placeholder="student@example.com" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Phone Number</label>
|
||||
<input type="text" name="phone" class="form-control" placeholder="07XXXXXXXX">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold text-success"><i class="fa-solid fa-key me-1"></i> Assign Portal PIN</label>
|
||||
<input type="text" name="pin" class="form-control fw-bold fs-5 text-center text-success" maxlength="6" placeholder="Enter PIN (e.g. 5678)" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<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-plus-circle me-1"></i> Create Access</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,711 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<title>Course Management - Admin Portal</title>
|
||||
|
||||
<!-- Font Awesome Icons & Bootstrap 5 -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--theme-navy: #2D355B;
|
||||
--theme-footer-navy: #1F2541;
|
||||
--theme-red: #822424;
|
||||
--theme-red-hover: #df2c3e;
|
||||
--theme-yellow: #FFEA85;
|
||||
--sidebar-width: 260px;
|
||||
--text-dark: #333333;
|
||||
--theme-bg: #F6F6F6;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--theme-bg);
|
||||
color: var(--text-dark);
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: var(--sidebar-width);
|
||||
height: 100vh;
|
||||
background: var(--theme-navy);
|
||||
color: #fff;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 24px 0;
|
||||
transition: all 0.3s ease;
|
||||
z-index: 1030;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 2px 0 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.sidebar .brand {
|
||||
padding: 0 24px 20px;
|
||||
font-weight: 700;
|
||||
font-size: 1.25rem;
|
||||
color: #ffffff;
|
||||
border-bottom: 1px solid rgba(255,255,255,.15);
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sidebar .admin-badge {
|
||||
background-color: var(--theme-red);
|
||||
font-size: 0.7rem;
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
margin-left: 8px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.sidebar .nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sidebar .nav-link {
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
padding: 14px 24px;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
transition: all 0.2s ease;
|
||||
border-left: 4px solid transparent;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sidebar .nav-link i {
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sidebar .nav-link:hover {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
color: var(--theme-yellow) !important;
|
||||
padding-left: 28px;
|
||||
}
|
||||
|
||||
.sidebar .nav-link.active {
|
||||
background: var(--theme-footer-navy);
|
||||
color: var(--theme-yellow) !important;
|
||||
border-left: 4px solid #F73F52;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.sidebar-user-profile {
|
||||
padding: 15px 24px;
|
||||
border-top: 1px solid rgba(255,255,255,.15);
|
||||
margin-top: auto;
|
||||
background: var(--theme-footer-navy);
|
||||
}
|
||||
|
||||
.main {
|
||||
margin-left: var(--sidebar-width);
|
||||
width: calc(100% - var(--sidebar-width));
|
||||
min-height: 100vh;
|
||||
padding: 40px;
|
||||
background: var(--theme-bg);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.mobile-header {
|
||||
display: none;
|
||||
background: var(--theme-navy);
|
||||
color: #ffffff;
|
||||
padding: 12px 20px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1020;
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.4rem;
|
||||
cursor: pointer;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.sidebar-overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0; left: 0; right: 0; bottom: 0;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 1025;
|
||||
}
|
||||
|
||||
.sidebar-overlay.show { display: block; }
|
||||
|
||||
@media (max-width: 991px) {
|
||||
.sidebar { left: calc(-1 * var(--sidebar-width)); }
|
||||
.sidebar.show { left: 0; }
|
||||
.main { margin-left: 0; padding: 85px 20px 20px 20px; width: 100%; }
|
||||
.mobile-header { display: flex; }
|
||||
}
|
||||
|
||||
.course-img-preview {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
object-fit: cover;
|
||||
border-radius: 6px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Mobile Top Navigation Bar -->
|
||||
<header class="mobile-header">
|
||||
<button class="sidebar-toggle" id="toggleBtn" aria-label="Toggle Sidebar">
|
||||
<i class="fa-solid fa-bars"></i>
|
||||
</button>
|
||||
<div class="fw-bold">Admin Panel</div>
|
||||
<a href="/admin/login" class="btn btn-sm btn-outline-light">Sign In</a>
|
||||
</header>
|
||||
|
||||
<div class="sidebar-overlay" id="sidebarOverlay"></div>
|
||||
|
||||
<!-- Sidebar Navigation -->
|
||||
<aside class="sidebar" id="sidebar">
|
||||
<div class="brand">
|
||||
<i class="fa-solid fa-car-side me-2"></i> AutoEdu
|
||||
<span class="admin-badge">Admin</span>
|
||||
</div>
|
||||
|
||||
<nav class="nav">
|
||||
<a href="{{ route('admin.dashboard') }}" class="nav-link">
|
||||
<i class="fa-solid fa-chart-line"></i> Admin Dashboard
|
||||
</a>
|
||||
<a href="{{ route('admin.mycourses') }}" class="nav-link active">
|
||||
<i class="fa-solid fa-book-bookmark"></i> Course Management
|
||||
</a>
|
||||
<a href="{{ route('admin.timetable') }}" class="nav-link">
|
||||
<i class="fa-solid fa-calendar-check"></i> Class Timetable
|
||||
</a>
|
||||
<a href="{{ route('admin.results') }}" class="nav-link">
|
||||
<i class="fa-solid fa-file-invoice-dollar"></i> Exam Results
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<div class="sidebar-user-profile">
|
||||
<div class="dropdown dropup">
|
||||
<a class="text-white text-decoration-none dropdown-toggle d-flex align-items-center gap-2" href="#" data-bs-toggle="dropdown">
|
||||
<i class="fa-solid fa-circle-user" style="font-size: 24px; color: var(--theme-yellow);"></i>
|
||||
<span>{{ session('admin_username', 'Admin') }}</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-start shadow w-100">
|
||||
<li>
|
||||
<button type="button" onclick="submitAdminLogout()" class="dropdown-item text-danger border-0 bg-transparent">
|
||||
<i class="fa-solid fa-right-from-bracket me-2"></i> Logout
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Main Content Area -->
|
||||
<main class="main">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h3 class="fw-bold"><i class="fa-solid fa-book-bookmark me-2"></i> Course Management</h3>
|
||||
<!-- Add New Course Button -->
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addCourseModal">
|
||||
<i class="fa-solid fa-plus me-1"></i> Add New Course
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Success/Error Alerts -->
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
{{ session('success') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(session('error'))
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
{{ session('error') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Courses Table Card -->
|
||||
<div class="card border-0 shadow-sm rounded-3">
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Image</th>
|
||||
<th>Code</th>
|
||||
<th>Title</th>
|
||||
<th>Duration</th>
|
||||
<th>Level</th>
|
||||
<th>Status</th>
|
||||
<th class="text-center">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($courses as $course)
|
||||
<tr>
|
||||
<td>{{ $loop->iteration }}</td>
|
||||
<td>
|
||||
@if($course->image)
|
||||
<img src="{{ asset('storage/' . $course->image) }}" class="course-img-preview" alt="Course Image">
|
||||
@else
|
||||
<span class="badge bg-secondary">No Image</span>
|
||||
@endif
|
||||
</td>
|
||||
<td><span class="badge bg-light text-dark border">{{ $course->course_code }}</span></td>
|
||||
<td class="fw-semibold">{{ $course->title }}</td>
|
||||
<td>{{ $course->duration }}</td>
|
||||
<td>{{ $course->level }}</td>
|
||||
<td>
|
||||
@if($course->status == 'Active')
|
||||
<span class="badge bg-success">Active</span>
|
||||
@else
|
||||
<span class="badge bg-secondary">Inactive</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<div class="d-flex justify-content-center gap-1">
|
||||
<!-- View Modules Button -->
|
||||
<button class="btn btn-sm btn-outline-info"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#modulesModal{{ $course->id }}">
|
||||
<i class="fa-solid fa-layer-group me-1"></i> Modules
|
||||
</button>
|
||||
|
||||
<!-- Edit Course Button -->
|
||||
<button class="btn btn-sm btn-outline-warning"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#editCourseModal{{ $course->id }}">
|
||||
<i class="fa-solid fa-pen-to-square"></i> Edit
|
||||
</button>
|
||||
|
||||
<!-- Delete Course Form -->
|
||||
<form action="{{ route('courses.destroy', $course->id) }}" method="POST" onsubmit="return confirm('Delete this course?')" class="d-inline">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="btn btn-sm btn-outline-danger">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- EDIT COURSE MODAL -->
|
||||
<div class="modal fade" id="editCourseModal{{ $course->id }}" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-white" style="background-color: var(--theme-navy);">
|
||||
<h5 class="modal-title fw-bold text-white"><i class="fa-solid fa-pen-to-square me-2"></i>Edit Course</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<!-- Fixed Route Name: admin.courses.update -->
|
||||
<form action="{{ route('admin.courses.update', $course->id) }}" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<div class="modal-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Course Code</label>
|
||||
<input type="text" name="course_code" class="form-control" value="{{ $course->course_code }}" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Course Title</label>
|
||||
<input type="text" name="title" class="form-control" value="{{ $course->title }}" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Duration</label>
|
||||
<input type="text" name="duration" class="form-control" value="{{ $course->duration }}" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Level</label>
|
||||
<select name="level" class="form-select" required>
|
||||
<option value="Certificate" {{ $course->level == 'Certificate' ? 'selected' : '' }}>Certificate</option>
|
||||
<option value="Diploma" {{ $course->level == 'Diploma' ? 'selected' : '' }}>Diploma</option>
|
||||
<option value="Advanced Diploma" {{ $course->level == 'Advanced Diploma' ? 'selected' : '' }}>Advanced Diploma</option>
|
||||
<option value="Degree" {{ $course->level == 'Degree' ? 'selected' : '' }}>Degree</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Status</label>
|
||||
<select name="status" class="form-select" required>
|
||||
<option value="Active" {{ $course->status == 'Active' ? 'selected' : '' }}>Active</option>
|
||||
<option value="Inactive" {{ $course->status == 'Inactive' ? 'selected' : '' }}>Inactive</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Course Image</label>
|
||||
<input type="file" name="image" class="form-control" accept="image/*">
|
||||
@if($course->image)
|
||||
<div class="mt-2">
|
||||
<small class="text-muted">Current Image:</small><br>
|
||||
<img src="{{ asset('storage/' . $course->image) }}" class="course-img-preview border mt-1" alt="Current Image">
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label fw-bold">Description</label>
|
||||
<textarea name="desc" class="form-control" rows="3">{{ $course->desc ?? '' }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-warning">Update Course</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MODULES MANAGEMENT MODAL -->
|
||||
<div class="modal fade" id="modulesModal{{ $course->id }}" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-white" style="background-color: var(--theme-navy);">
|
||||
<h5 class="modal-title fw-bold text-white">
|
||||
<i class="fa-solid fa-layer-group me-2"></i>Modules - {{ $course->title }} ({{ $course->course_code }})
|
||||
</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body bg-light">
|
||||
<div class="row g-4">
|
||||
<!-- Left Side: Modules List by Semester -->
|
||||
<div class="col-lg-7">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-header bg-white fw-bold py-3">
|
||||
<i class="fa-solid fa-list-check me-2 text-primary"></i>Course Modules List
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@php
|
||||
$groupedModules = $course->modules ? $course->modules->groupBy('semester') : collect();
|
||||
@endphp
|
||||
|
||||
@forelse($groupedModules as $semester => $modules)
|
||||
<div class="mb-4">
|
||||
<h6 class="fw-bold text-uppercase text-secondary border-bottom pb-2">
|
||||
<i class="fa-solid fa-calendar-week me-2"></i>{{ $semester }}
|
||||
</h6>
|
||||
<div class="list-group">
|
||||
@foreach($modules as $module)
|
||||
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<span class="badge bg-secondary me-2">{{ $module->module_code }}</span>
|
||||
<strong class="text-dark">{{ $module->title }}</strong>
|
||||
@if($module->credits)
|
||||
<span class="small text-muted ms-2">({{ $module->credits }} Credits)</span>
|
||||
@endif
|
||||
@if($module->description)
|
||||
<p class="mb-0 text-muted small mt-1">{{ $module->description }}</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<button class="btn btn-sm btn-outline-warning"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#editModuleCollapse{{ $module->id }}">
|
||||
<i class="fa-solid fa-pen"></i>
|
||||
</button>
|
||||
|
||||
<!-- Fixed Route Name: modules.delete -->
|
||||
<form action="{{ route('modules.delete', $module->id) }}" method="POST" onsubmit="return confirm('Delete this module?')" class="d-inline">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="btn btn-sm btn-outline-danger">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit Module Collapse Form -->
|
||||
<div class="collapse mt-2 p-3 bg-white border rounded" id="editModuleCollapse{{ $module->id }}">
|
||||
<!-- Fixed Route Name: modules.update -->
|
||||
<form action="{{ route('modules.update', $module->id) }}" method="POST">
|
||||
@csrf
|
||||
<h6 class="fw-bold text-warning mb-3"><i class="fa-solid fa-pen-to-square me-1"></i>Edit Module</h6>
|
||||
<div class="row g-2">
|
||||
<div class="col-md-4">
|
||||
<input type="text" name="module_code" class="form-control form-control-sm" value="{{ $module->module_code }}" placeholder="Code" required>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<input type="text" name="title" class="form-control form-control-sm" value="{{ $module->title }}" placeholder="Title" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<select name="semester" class="form-select form-select-sm" required>
|
||||
<option value="Semester 1" {{ $module->semester == 'Semester 1' ? 'selected' : '' }}>Semester 1</option>
|
||||
<option value="Semester 2" {{ $module->semester == 'Semester 2' ? 'selected' : '' }}>Semester 2</option>
|
||||
<option value="Semester 3" {{ $module->semester == 'Semester 3' ? 'selected' : '' }}>Semester 3</option>
|
||||
<option value="Semester 4" {{ $module->semester == 'Semester 4' ? 'selected' : '' }}>Semester 4</option>
|
||||
<option value="Year 1" {{ $module->semester == 'Year 1' ? 'selected' : '' }}>Year 1</option>
|
||||
<option value="Year 2" {{ $module->semester == 'Year 2' ? 'selected' : '' }}>Year 2</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<input type="number" name="credits" class="form-control form-control-sm" value="{{ $module->credits }}" placeholder="Credits">
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<textarea name="description" class="form-control form-control-sm" rows="2" placeholder="Description">{{ $module->description }}</textarea>
|
||||
</div>
|
||||
<div class="col-md-12 text-end mt-2">
|
||||
<button type="submit" class="btn btn-sm btn-warning">Update Module</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<div class="text-center py-4 text-muted">
|
||||
<i class="fa-solid fa-circle-info fa-2x mb-2 text-secondary"></i>
|
||||
<p class="mb-0">No modules added yet for this course.</p>
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Side: Add New Module Form -->
|
||||
<div class="col-lg-5">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-header bg-white fw-bold py-3">
|
||||
<i class="fa-solid fa-plus-circle me-2 text-success"></i>Add New Module
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- Fixed Route Name: modules.store -->
|
||||
<form action="{{ route('modules.store') }}" method="POST">
|
||||
@csrf
|
||||
<input type="hidden" name="course_id" value="{{ $course->id }}">
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Semester</label>
|
||||
<select name="semester" class="form-select" required>
|
||||
<option value="Semester 1.1">Semester 1.1</option>
|
||||
<option value="Semester 1.2">Semester 1.2</option>
|
||||
<option value="Semester 2.1">Semester 2.1</option>
|
||||
<option value="Semester 2.2">Semester 2.2</option>
|
||||
<option value="Semester 3.1">Semester 3.1</option>
|
||||
<option value="Semester 3.2">Semester 3.2</option>
|
||||
<option value="Semester 4.1">Semester 4.1</option>
|
||||
<option value="Semester 4.2">Semester 4.2</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Module Code</label>
|
||||
<input type="text" name="module_code" class="form-control" placeholder="e.g. MOD101" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Module Title</label>
|
||||
<input type="text" name="title" class="form-control" placeholder="Module Title" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Credits</label>
|
||||
<input type="number" name="credits" class="form-control" placeholder="Credits">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Description</label>
|
||||
<textarea name="description" class="form-control" rows="3" placeholder="Description"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success w-100">
|
||||
<i class="fa-solid fa-plus me-1"></i> Add Module
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="8" class="text-center py-4 text-muted">No courses found. Click "Add New Course" to create one.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Assign Courses to Students -->
|
||||
<div class="card border-0 shadow-sm rounded-3 mt-4">
|
||||
<div class="card-body d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h5 class="fw-bold mb-1"><i class="fa-solid fa-user-graduate me-2 text-primary"></i>Assign Courses to Students</h5>
|
||||
<p class="text-muted mb-0 small">Enroll one or more students into an existing course.</p>
|
||||
</div>
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#assignCourseModal">
|
||||
<i class="fa-solid fa-user-plus me-1"></i> Assign Course
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- ASSIGN COURSE TO STUDENTS MODAL -->
|
||||
<div class="modal fade" id="assignCourseModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-white" style="background-color: var(--theme-navy);">
|
||||
<h5 class="modal-title fw-bold text-white"><i class="fa-solid fa-user-plus me-2"></i>Assign Course to Students</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
|
||||
<!-- Route name: assign.course -->
|
||||
<form action="{{ route('assign.course') }}" method="POST">
|
||||
@csrf
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Select Course</label>
|
||||
<select name="course_id" class="form-select" required>
|
||||
<option value="" selected disabled>-- Choose Course --</option>
|
||||
@foreach($courses as $course)
|
||||
<option value="{{ $course->id }}">{{ $course->course_code }} - {{ $course->title }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Select Student(s)</label>
|
||||
<select name="student_ids[]" class="form-select" multiple size="8" required>
|
||||
@forelse($students as $student)
|
||||
<option value="{{ $student->id }}">{{ $student->full_name }} ({{ $student->student_id ?? $student->email }})</option>
|
||||
@empty
|
||||
<option value="" disabled>No students found</option>
|
||||
@endforelse
|
||||
</select>
|
||||
<small class="text-muted">Hold Ctrl (Windows) / Cmd (Mac) to select multiple students.</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fa-solid fa-check me-1"></i> Assign Course
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ADD NEW COURSE MODAL -->
|
||||
<div class="modal fade" id="addCourseModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header text-white" style="background-color: var(--theme-navy);">
|
||||
<h5 class="modal-title fw-bold text-white"><i class="fa-solid fa-plus-circle me-2"></i>Add New Course</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<!-- Fixed Route Name: admin.courses.store -->
|
||||
<form action="{{ route('admin.courses.store') }}" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<div class="modal-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Course Code</label>
|
||||
<input type="text" name="course_code" class="form-control" placeholder="e.g. DSE101" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Course Title</label>
|
||||
<input type="text" name="title" class="form-control" placeholder="e.g. Diploma in Software Engineering" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Duration</label>
|
||||
<input type="text" name="duration" class="form-control" placeholder="e.g. 1 Year / 6 Months" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Level</label>
|
||||
<select name="level" class="form-select" required>
|
||||
<option value="" selected disabled>Select Level</option>
|
||||
<option value="Certificate">Certificate</option>
|
||||
<option value="Diploma">Diploma</option>
|
||||
<option value="Advanced Diploma">Advanced Diploma</option>
|
||||
<option value="Degree">Degree</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Status</label>
|
||||
<select name="status" class="form-select" required>
|
||||
<option value="Active" selected>Active</option>
|
||||
<option value="Inactive">Inactive</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Course Image</label>
|
||||
<input type="file" name="image" class="form-control" accept="image/*">
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label fw-bold">Description</label>
|
||||
<textarea name="description" class="form-control" rows="3" placeholder="Brief course description..."></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Save Course</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Logout Form -->
|
||||
<form id="adminLogoutForm" action="{{ route('admin.logout') }}" method="POST" class="d-none">
|
||||
@csrf
|
||||
</form>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
const sidebar = document.getElementById('sidebar');
|
||||
const overlay = document.getElementById('sidebarOverlay');
|
||||
const toggleBtn = document.getElementById('toggleBtn');
|
||||
|
||||
if(toggleBtn) {
|
||||
toggleBtn.addEventListener('click', () => {
|
||||
sidebar.classList.toggle('show');
|
||||
overlay.classList.toggle('show');
|
||||
});
|
||||
}
|
||||
|
||||
if(overlay) {
|
||||
overlay.addEventListener('click', () => {
|
||||
sidebar.classList.remove('show');
|
||||
overlay.classList.remove('show');
|
||||
});
|
||||
}
|
||||
|
||||
function submitAdminLogout() {
|
||||
document.getElementById('adminLogoutForm').submit();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
@extends('layouts.adminnav')
|
||||
|
||||
@section('title', 'Admin Profile - Admin Panel')
|
||||
|
||||
@section('content')
|
||||
<div class="container py-4">
|
||||
<div class="row">
|
||||
<div class="col-12 mb-4">
|
||||
<h3 class="fw-bold text-navy">
|
||||
<i class="fa-solid fa-user-gear me-2"></i>Admin Profile Management
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Success & Error Alerts -->
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible fade show mb-4" role="alert">
|
||||
<i class="fa-solid fa-circle-check me-2"></i>{{ session('success') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($errors->any())
|
||||
<div class="alert alert-danger alert-dismissible fade show mb-4" role="alert">
|
||||
<i class="fa-solid fa-triangle-exclamation me-2"></i>
|
||||
<strong>Please check the form for errors:</strong>
|
||||
<ul class="mb-0 mt-1">
|
||||
@foreach($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="row g-4">
|
||||
<!-- Profile Summary Card -->
|
||||
<div class="col-lg-4">
|
||||
<div class="card border-0 shadow-sm rounded-3 text-center p-4">
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<div class="rounded-circle bg-navy text-white d-inline-flex align-items-center justify-content-center shadow" style="width: 100px; height: 100px; font-size: 40px;">
|
||||
<i class="fa-solid fa-user-shield"></i>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="fw-bold mb-1">{{ $admin->username ?? 'Administrator' }}</h4>
|
||||
<span class="badge bg-danger fs-6 px-3 py-2 rounded-pill mt-2">System Administrator</span>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<div class="text-start">
|
||||
<p class="mb-2"><strong><i class="fa-solid fa-id-badge text-navy me-2"></i>Admin ID:</strong> {{ $admin->id ?? session('admin_id') }}</p>
|
||||
<p class="mb-2"><strong><i class="fa-solid fa-user text-navy me-2"></i>Username:</strong> {{ $admin->username ?? 'N/A' }}</p>
|
||||
<p class="mb-0"><strong><i class="fa-solid fa-clock text-navy me-2"></i>Created At:</strong> {{ isset($admin->created_at) ? $admin->created_at->format('Y-m-d') : 'N/A' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit Profile & Password Forms -->
|
||||
<div class="col-lg-8">
|
||||
<!-- Update Username Card -->
|
||||
<div class="card border-0 shadow-sm rounded-3 mb-4">
|
||||
<div class="card-header bg-white py-3 border-0">
|
||||
<h5 class="fw-bold mb-0 text-navy">
|
||||
<i class="fa-solid fa-pen-to-square me-2"></i>Update Account Details
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="{{ route('admin.profile.update') }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-bold">Username</label>
|
||||
<input type="text" name="username" class="form-control" value="{{ old('username', $admin->username ?? '') }}" required>
|
||||
</div>
|
||||
<div class="col-12 text-end mt-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fa-solid fa-floppy-disk me-1"></i> Save Changes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Change Password Card -->
|
||||
<div class="card border-0 shadow-sm rounded-3">
|
||||
<div class="card-header bg-white py-3 border-0">
|
||||
<h5 class="fw-bold mb-0 text-navy">
|
||||
<i class="fa-solid fa-key me-2"></i>Change Password
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="{{ route('admin.profile.password') }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-bold">Current Password</label>
|
||||
<input type="password" name="current_password" class="form-control" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">New Password</label>
|
||||
<input type="password" name="new_password" class="form-control" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Confirm New Password</label>
|
||||
<input type="password" name="new_password_confirmation" class="form-control" required>
|
||||
</div>
|
||||
<div class="col-12 text-end mt-4">
|
||||
<button type="submit" class="btn btn-danger">
|
||||
<i class="fa-solid fa-shield-halved me-1"></i> Update Password
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,307 @@
|
|||
@extends('layouts.adminnav')
|
||||
|
||||
@section('title', 'Exam Results Management - Admin Panel')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h3 class="fw-bold text-navy">
|
||||
<i class="fa-solid fa-square-poll-vertical me-2"></i>Exam Results Management
|
||||
</h3>
|
||||
<div>
|
||||
<!-- Import Excel Button -->
|
||||
<button class="btn btn-success me-2" data-bs-toggle="modal" data-bs-target="#importExcelModal">
|
||||
<i class="fa-solid fa-file-excel me-1"></i> Import Excel
|
||||
</button>
|
||||
<!-- Add Single Result Button -->
|
||||
<button class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#addResultModal">
|
||||
<i class="fa-solid fa-plus me-1"></i> Add New Result
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<i class="fa-solid fa-circle-check me-2"></i>{{ session('success') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($errors->any())
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<i class="fa-solid fa-triangle-exclamation me-2"></i>
|
||||
<strong>Please fix the following errors:</strong>
|
||||
<ul class="mb-0 mt-1">
|
||||
@foreach($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
|
||||
<!-- Filter & Search Section -->
|
||||
<div class="card border-0 shadow-sm rounded-3 mb-4">
|
||||
<div class="card-body">
|
||||
<form action="{{ route('admin.results.index') }}" method="GET">
|
||||
<div class="row g-3 align-items-end">
|
||||
<!-- Search Box -->
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-bold small text-secondary">Search</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-white"><i class="fa-solid fa-magnifying-glass text-muted"></i></span>
|
||||
<input type="text" name="search" class="form-control" placeholder="Student ID, Module Code/Name..." value="{{ request('search') }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Academic Year Filter -->
|
||||
<div class="col-md-3">
|
||||
<label class="form-label fw-bold small text-secondary">Academic Year</label>
|
||||
<input type="text" name="academic_year" class="form-control" placeholder="e.g. 2025/2026" value="{{ request('academic_year') }}">
|
||||
</div>
|
||||
|
||||
<!-- Status Filter -->
|
||||
<div class="col-md-3">
|
||||
<label class="form-label fw-bold small text-secondary">Status</label>
|
||||
<select name="status" class="form-select">
|
||||
<option value="">All Statuses</option>
|
||||
<option value="Pass" {{ request('status') == 'Pass' ? 'selected' : '' }}>Pass</option>
|
||||
<option value="Fail" {{ request('status') == 'Fail' ? 'selected' : '' }}>Fail</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Filter & Reset Buttons -->
|
||||
<div class="col-md-2 d-flex gap-2">
|
||||
<button type="submit" class="btn btn-navy text-white w-100" style="background-color: #0a192f;">
|
||||
<i class="fa-solid fa-filter me-1"></i> Filter
|
||||
</button>
|
||||
<a href="{{ route('admin.results.index') }}" class="btn btn-outline-secondary" title="Reset Filters">
|
||||
<i class="fa-solid fa-rotate-left"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Results Table -->
|
||||
<div class="card border-0 shadow-sm rounded-3">
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="table-dark">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Student Log ID</th>
|
||||
<th>Module Code</th>
|
||||
<th>Module Name</th>
|
||||
<th>Academic Year</th>
|
||||
<th>Semester</th>
|
||||
<th>Marks</th>
|
||||
<th>Grade</th>
|
||||
<th>Status</th>
|
||||
<th class="text-center">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($results as $result)
|
||||
<tr>
|
||||
<td>{{ $result->id }}</td>
|
||||
<td><span class="badge bg-secondary">{{ $result->student_log_id }}</span></td>
|
||||
<td><strong>{{ $result->module_code }}</strong></td>
|
||||
<td>{{ $result->module_name }}</td>
|
||||
<td>{{ $result->academic_year }}</td>
|
||||
<td>{{ $result->semester }}</td>
|
||||
<td><span class="fw-bold">{{ $result->marks }}</span></td>
|
||||
<td>
|
||||
<span class="badge bg-primary fs-6">{{ $result->grade }}</span>
|
||||
</td>
|
||||
<td>
|
||||
@if(strtolower($result->status) == 'pass')
|
||||
<span class="badge bg-success">Pass</span>
|
||||
@else
|
||||
<span class="badge bg-danger">Fail</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<!-- Edit Button -->
|
||||
<button class="btn btn-sm btn-outline-primary me-1"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#editResultModal{{ $result->id }}">
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
</button>
|
||||
|
||||
<!-- Delete Button -->
|
||||
<form action="{{ route('admin.results.delete', $result->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this result?');">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="btn btn-sm btn-outline-danger">
|
||||
<i class="fa-solid fa-trash-can"></i>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Edit Result Modal -->
|
||||
<div class="modal fade" id="editResultModal{{ $result->id }}" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-navy text-white">
|
||||
<h5 class="modal-title"><i class="fa-solid fa-pen-to-square me-2"></i>Edit Student Result</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<form action="{{ route('admin.results.update', $result->id) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
<div class="modal-body text-start">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Student Log ID</label>
|
||||
<input type="text" name="student_log_id" class="form-control" value="{{ $result->student_log_id }}" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Module Code</label>
|
||||
<input type="text" name="module_code" class="form-control" value="{{ $result->module_code }}" required>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-bold">Module Name</label>
|
||||
<input type="text" name="module_name" class="form-control" value="{{ $result->module_name }}" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Academic Year</label>
|
||||
<input type="text" name="academic_year" class="form-control" value="{{ $result->academic_year }}" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Semester</label>
|
||||
<input type="text" name="semester" class="form-control" value="{{ $result->semester }}" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-bold">Marks</label>
|
||||
<input type="number" step="0.01" name="marks" class="form-control" value="{{ $result->marks }}" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-bold">Grade</label>
|
||||
<input type="text" name="grade" class="form-control" value="{{ $result->grade }}" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-bold">Status</label>
|
||||
<select name="status" class="form-select" required>
|
||||
<option value="Pass" {{ $result->status == 'Pass' ? 'selected' : '' }}>Pass</option>
|
||||
<option value="Fail" {{ $result->status == 'Fail' ? 'selected' : '' }}>Fail</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Update Result</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="10" class="text-center py-4 text-muted">No examination results found.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Import Excel Modal -->
|
||||
<div class="modal fade" id="importExcelModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-success text-white">
|
||||
<h5 class="modal-title"><i class="fa-solid fa-file-excel me-2"></i>Import Results Excel File</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<form action="{{ route('admin.results.import') }}" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Choose Excel File (.xlsx, .xls, .csv)</label>
|
||||
<input type="file" name="excel_file" class="form-control" accept=".xlsx, .xls, .csv" required>
|
||||
</div>
|
||||
<div class="alert alert-info py-2 small mb-0">
|
||||
<i class="fa-solid fa-circle-info me-1"></i>This Excel <strong>Headers</strong>that should be included in the file for successful import:
|
||||
<br><code>student_log_id</code>, <code>module_code</code>, <code>module_name</code>, <code>academic_year</code>, <code>semester</code>, <code>marks</code>, <code>grade</code>, <code>status</code>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-success"><i class="fa-solid fa-upload me-1"></i> Upload & Process</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Result Modal -->
|
||||
<div class="modal fade" id="addResultModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-navy text-white">
|
||||
<h5 class="modal-title"><i class="fa-solid fa-plus-circle me-2"></i>Add New Examination Result</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<form action="{{ route('admin.results.store') }}" method="POST">
|
||||
@csrf
|
||||
<div class="modal-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Student Log ID</label>
|
||||
<input type="text" name="student_log_id" class="form-control" placeholder="e.g. ST1001" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Module Code</label>
|
||||
<input type="text" name="module_code" class="form-control" placeholder="e.g. AME201" required>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-bold">Module Name</label>
|
||||
<input type="text" name="module_name" class="form-control" placeholder="e.g. Automobile Technology II" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Academic Year</label>
|
||||
<input type="text" name="academic_year" class="form-control" placeholder="e.g. 2025/2026" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">Semester</label>
|
||||
<input type="text" name="semester" class="form-control" placeholder="e.g. Semester 1" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-bold">Marks</label>
|
||||
<input type="number" step="0.01" name="marks" class="form-control" placeholder="0 - 100" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-bold">Grade</label>
|
||||
<input type="text" name="grade" class="form-control" placeholder="e.g. A+, B, C" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label fw-bold">Status</label>
|
||||
<select name="status" class="form-select" required>
|
||||
<option value="Pass">Pass</option>
|
||||
<option value="Fail">Fail</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-success"><i class="fa-solid fa-floppy-disk me-1"></i> Save Result</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,296 @@
|
|||
@extends('layouts.adminnav')
|
||||
|
||||
@section('title', 'Admin Timetable Management')
|
||||
|
||||
@section('content')
|
||||
<style>
|
||||
.bg-custom-header {
|
||||
background: linear-gradient(135deg, #2c2a4a 0%, #4a4773 100%);
|
||||
color: white;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
/* Badge Colors matching the design */
|
||||
.badge-type {
|
||||
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; }
|
||||
|
||||
/* Table Custom Styles */
|
||||
.table-timetable {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.table-timetable th {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
font-weight: 700;
|
||||
padding: 14px 10px;
|
||||
color: #334155;
|
||||
background-color: #f8fafc;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
}
|
||||
.table-timetable td {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
height: 90px;
|
||||
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 {
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s ease-in-out;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.timetable-cell:hover {
|
||||
background-color: #f1f5f9;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* Today's Red Header Highlight */
|
||||
.today-header {
|
||||
background-color: #d9383a !important;
|
||||
color: white !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container-fluid py-4">
|
||||
|
||||
<!-- Header Banner -->
|
||||
<div class="p-4 mb-4 bg-custom-header shadow-sm d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h3 class="fw-bold mb-1"><i class="fa-solid fa-calendar-days me-2"></i>My Class Timetable</h3>
|
||||
<p class="mb-0 text-white-50 small">Automobile Engineering Academy Timetable Management</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Alert Messages -->
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible fade show mb-4" role="alert">
|
||||
<i class="fa-solid fa-circle-check me-2"></i>{{ session('success') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="row g-4 mb-4">
|
||||
<!-- Today's Schedule Card -->
|
||||
<div class="col-lg-5">
|
||||
<div class="card border-0 shadow-sm rounded-3 h-100">
|
||||
<div class="card-header bg-white py-3 border-0">
|
||||
<h6 class="fw-bold mb-0 text-danger">
|
||||
<i class="fa-solid fa-clock me-2"></i>Today's Schedule ({{ $today }})
|
||||
</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@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>
|
||||
<span class="badge badge-type badge-{{ strtolower($item->type) }} mb-1">{{ $item->type }}</span>
|
||||
<h6 class="fw-bold mb-0 text-dark">{{ $item->subject_name }}</h6>
|
||||
</div>
|
||||
<small class="text-muted fw-bold">{{ $item->time_slot }}</small>
|
||||
</div>
|
||||
@empty
|
||||
<p class="text-muted text-center py-4 mb-0">No classes scheduled for today.</p>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Legend Card -->
|
||||
<div class="col-lg-7">
|
||||
<div class="card border-0 shadow-sm rounded-3 h-100">
|
||||
<div class="card-header bg-white py-3 border-0">
|
||||
<h6 class="fw-bold mb-0 text-primary">
|
||||
<i class="fa-solid fa-layer-group me-2"></i>Timetable Legend
|
||||
</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-flex flex-wrap gap-2 mb-3">
|
||||
<span class="badge badge-type badge-theory">Theory</span>
|
||||
<span class="badge badge-type badge-practical">Practical</span>
|
||||
<span class="badge badge-type badge-workshop">Workshop</span>
|
||||
<span class="badge badge-type badge-exam">Exam</span>
|
||||
</div>
|
||||
<hr>
|
||||
<p class="text-muted small mb-0">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Timetable Grid -->
|
||||
<div class="card border-0 shadow-sm rounded-3">
|
||||
<div class="card-body p-3">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-timetable mb-0 align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 15%;">Time</th>
|
||||
@foreach($days as $day)
|
||||
<th class="{{ strtolower($today) == strtolower($day) ? 'today-header' : '' }}">
|
||||
{{ $day }} {{ strtolower($today) == strtolower($day) ? '(Today)' : '' }}
|
||||
</th>
|
||||
@endforeach
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($timeSlots as $slot)
|
||||
<tr>
|
||||
<!-- Time Column -->
|
||||
<td class="fw-bold text-secondary bg-light" style="font-size: 13px;">{{ $slot }}</td>
|
||||
|
||||
@if($slot == '12:30 - 01:30')
|
||||
<!-- Lunch / Rest Time Row -->
|
||||
<td colspan="5" class="bg-light text-center fw-bold text-secondary py-3" style="letter-spacing: 0.5px;">
|
||||
🍱 LUNCH BREAK / REST TIME
|
||||
</td>
|
||||
@else
|
||||
<!-- Days Columns -->
|
||||
@foreach($days as $day)
|
||||
@php
|
||||
$item = $grid[$slot][$day] ?? null;
|
||||
@endphp
|
||||
<td>
|
||||
<div class="timetable-cell"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#editSlotModal"
|
||||
onclick="openEditModal('{{ $day }}', '{{ $slot }}', '{{ $item->subject_name ?? '' }}', '{{ $item->type ?? 'Theory' }}', '{{ $item->id ?? '' }}')">
|
||||
|
||||
@if($item)
|
||||
<span class="badge badge-type badge-{{ strtolower($item->type) }} mb-1">
|
||||
{{ $item->type }}
|
||||
</span>
|
||||
<div class="fw-bold text-dark small">{{ $item->subject_name }}</div>
|
||||
@else
|
||||
<span class="text-muted small opacity-50"><i class="fa-solid fa-plus text-primary me-1"></i>Add</span>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</td>
|
||||
@endforeach
|
||||
@endif
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal for Edit / Add Slot -->
|
||||
<div class="modal fade" id="editSlotModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header bg-custom-header text-white">
|
||||
<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>
|
||||
</div>
|
||||
<form action="{{ route('admin.timetable.store') }}" method="POST">
|
||||
@csrf
|
||||
<input type="hidden" name="day" id="modal_day">
|
||||
<input type="hidden" name="time_slot" id="modal_time_slot">
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Day & Time Slot</label>
|
||||
<input type="text" id="display_day_time" class="form-control bg-light" readonly>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<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 Fundamentals" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Subject Type</label>
|
||||
<select name="type" id="modal_type" class="form-select" required>
|
||||
<option value="Theory">Theory</option>
|
||||
<option value="Practical">Practical</option>
|
||||
<option value="Workshop">Workshop</option>
|
||||
<!-- <option value="Exam">Exam</option> -->
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer d-flex justify-content-between">
|
||||
<button type="button" id="clearBtn" class="btn btn-outline-danger d-none" onclick="clearSlotData()">
|
||||
<i class="fa-solid fa-trash me-1"></i> Clear Slot
|
||||
</button>
|
||||
<div>
|
||||
<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 Changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Hidden Form to Clear Slot -->
|
||||
<form id="deleteSlotForm" method="POST" class="d-none">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var currentSlotId = null;
|
||||
|
||||
function openEditModal(day, timeSlot, subject, type, id) {
|
||||
document.getElementById('modal_day').value = day;
|
||||
document.getElementById('modal_time_slot').value = timeSlot;
|
||||
document.getElementById('display_day_time').value = day + ' (' + timeSlot + ')';
|
||||
document.getElementById('modal_subject').value = subject;
|
||||
document.getElementById('modal_type').value = type || 'Theory';
|
||||
|
||||
currentSlotId = id;
|
||||
var clearBtn = document.getElementById('clearBtn');
|
||||
var modalTitle = document.getElementById('modalTitle');
|
||||
|
||||
if(id) {
|
||||
clearBtn.classList.remove('d-none');
|
||||
modalTitle.innerHTML = '<i class="fa-solid fa-pen-to-square me-2"></i>Edit Class Slot';
|
||||
} else {
|
||||
clearBtn.classList.add('d-none');
|
||||
modalTitle.innerHTML = '<i class="fa-solid fa-plus me-2"></i>Add Class Slot';
|
||||
}
|
||||
}
|
||||
|
||||
function clearSlotData() {
|
||||
if(currentSlotId && confirm('Are you sure you want to clear this timetable slot?')) {
|
||||
var form = document.getElementById('deleteSlotForm');
|
||||
form.action = "/admin/timetable/delete/" + currentSlotId;
|
||||
form.submit();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<title>Admin Login - AutoEdu</title>
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--theme-navy: #2D355B;
|
||||
--theme-red: #822424;
|
||||
--theme-yellow: #FFEA85;
|
||||
--theme-bg: #F6F6F6;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--theme-bg);
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
}
|
||||
|
||||
.login-card {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
border: none;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.login-header {
|
||||
background: var(--theme-navy);
|
||||
color: #fff;
|
||||
padding: 25px 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-theme-red {
|
||||
background-color: var(--theme-red);
|
||||
color: #fff;
|
||||
border: none;
|
||||
padding: 12px;
|
||||
font-weight: 600;
|
||||
border-radius: 8px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.btn-theme-red:hover {
|
||||
background-color: #a32d2d;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="login-card">
|
||||
<div class="login-header">
|
||||
<i class="fa-solid fa-user-shield fa-2x mb-2" style="color: var(--theme-yellow);"></i>
|
||||
<h5 class="fw-bold mb-0">Admin Login</h5>
|
||||
</div>
|
||||
|
||||
<div class="p-4">
|
||||
<!-- Error Alert -->
|
||||
<div id="errorAlert" class="alert alert-danger d-none py-2 text-center small" role="alert"></div>
|
||||
|
||||
<form id="adminLoginForm">
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold text-dark">Username</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="fa-solid fa-user"></i></span>
|
||||
<input type="text" id="username" class="form-control" placeholder="Username" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-semibold text-dark">Password</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="fa-solid fa-lock"></i></span>
|
||||
<input type="password" id="password" class="form-control" placeholder="Password" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-theme-red w-100" id="loginBtn">
|
||||
<i class="fa-solid fa-right-to-bracket me-2"></i> Login
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.getElementById('adminLoginForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const username = document.getElementById('username').value;
|
||||
const password = document.getElementById('password').value;
|
||||
const errorAlert = document.getElementById('errorAlert');
|
||||
const loginBtn = document.getElementById('loginBtn');
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
||||
|
||||
errorAlert.classList.add('d-none');
|
||||
loginBtn.disabled = true;
|
||||
loginBtn.innerHTML = '<i class="fa-solid fa-spinner fa-spin me-2"></i> Logging in...';
|
||||
|
||||
fetch('/admin/login', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'X-CSRF-TOKEN': csrfToken
|
||||
},
|
||||
body: JSON.stringify({ username: username, password: password })
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
window.location.href = '/admin/adminmycourses';
|
||||
} else {
|
||||
errorAlert.innerText = data.message || 'Login failed!';
|
||||
errorAlert.classList.remove('d-none');
|
||||
loginBtn.disabled = false;
|
||||
loginBtn.innerHTML = '<i class="fa-solid fa-right-to-bracket me-2"></i> Login';
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Error:', err);
|
||||
errorAlert.innerText = 'Server error occurred!';
|
||||
errorAlert.classList.remove('d-none');
|
||||
loginBtn.disabled = false;
|
||||
loginBtn.innerHTML = '<i class="fa-solid fa-right-to-bracket me-2"></i> Login';
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -6,136 +6,184 @@
|
|||
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
background: #f5f5f5;
|
||||
font-family: 'Segoe UI', Arial, Helvetica, sans-serif;
|
||||
background: #F8FAFC;
|
||||
color: #1E293B;
|
||||
}
|
||||
|
||||
:root {
|
||||
--primary: #5E244E;
|
||||
--secondary: #8B3A74;
|
||||
--light: #F8F4F7;
|
||||
/* Premium Modern Automotive Palette */
|
||||
--primary: #0F2C59;
|
||||
--secondary: #822424;
|
||||
--secondary-hover: #6a2525;
|
||||
--accent-yellow: #FFE618;
|
||||
--bg-light: #F8FAFC;
|
||||
--text-main: #1E293B;
|
||||
--card-border: rgba(62, 81, 184, 0.12);
|
||||
}
|
||||
|
||||
|
||||
|
||||
.hero {
|
||||
height: 220px;
|
||||
background: linear-gradient(rgba(20,20,20,.55),rgba(20,20,20,.55)),
|
||||
url('https://images.unsplash.com/photo-1517520287167-4bbf64a00d66?auto=format&fit=crop&w=1600&q=80');
|
||||
height: 240px;
|
||||
background: linear-gradient(rgba(214, 219, 255, 0.79), rgba(0, 0, 0, 0.85)), url('https://images.unsplash.com/photo-1517520287167-4bbf64a00d66?auto=format&fit=crop&w=1600&q=80');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
font-size: 36px;
|
||||
font-weight: 800;
|
||||
margin: 0;
|
||||
letter-spacing: -0.5px;
|
||||
}
|
||||
|
||||
.apply-area {
|
||||
margin-top: -40px;
|
||||
margin-bottom: 40px;
|
||||
margin-top: -50px;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
|
||||
.form-container-sm {
|
||||
max-width: 820px;
|
||||
max-width: 850px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.form-card {
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,.08);
|
||||
border: 1px solid var(--card-border);
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.form-header {
|
||||
background: var(--primary);
|
||||
background: linear-gradient(135deg, #8C4242 0%, #161414fa 100%);
|
||||
color: white;
|
||||
padding: 15px 25px;
|
||||
padding: 25px 30px;
|
||||
border-bottom: 3px solid var(--accent-yellow);
|
||||
}
|
||||
|
||||
.form-header h2 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
background: #735D6D;
|
||||
background: var(--secondary);
|
||||
color: white;
|
||||
padding: 8px 12px;
|
||||
margin-top: 22px;
|
||||
margin-bottom: 15px;
|
||||
padding: 10px 16px;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 20px;
|
||||
font-size: 14px;
|
||||
border-radius: 5px;
|
||||
border-radius: 6px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
box-shadow: 0 4px 10px rgba(106, 37, 37, 0.15);
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
margin-bottom: 4px;
|
||||
margin-bottom: 6px;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.form-control,
|
||||
.form-select {
|
||||
border-radius: 5px;
|
||||
padding: 6px 10px;
|
||||
font-size: 13px;
|
||||
border: 1px solid #cbd5e1;
|
||||
border-radius: 8px;
|
||||
padding: 10px 14px;
|
||||
font-size: 14px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.form-control:focus,
|
||||
.form-select:focus {
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 0 0 4px rgba(62, 81, 184, 0.15);
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.required {
|
||||
color: red;
|
||||
color: var(--secondary-hover);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
background: var(--primary);
|
||||
background:var(--secondary);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 20px;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
border-radius: 30px;
|
||||
padding: 14px 30px;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
transition: 0.3s ease;
|
||||
transition: all 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);
|
||||
box-shadow: 0 4px 12px rgba(62, 81, 184, 0.2);
|
||||
}
|
||||
|
||||
.submit-btn:hover {
|
||||
background: var(--secondary);
|
||||
transform: translateY(-1px);
|
||||
background: linear-gradient(135deg, var(--secondary) 0%, var(--secondary-hover) 100%);
|
||||
color: var(--accent-yellow);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(130, 36, 36, 0.35);
|
||||
}
|
||||
|
||||
|
||||
.mb-3-custom {
|
||||
margin-bottom: 0.75rem !important;
|
||||
margin-bottom: 1.25rem !important;
|
||||
}
|
||||
|
||||
.form-check-input:checked {
|
||||
background-color: var(--primary);
|
||||
border-color: var(--primary);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="hero">
|
||||
<div class="text-center">
|
||||
<div class="text-center px-3">
|
||||
<h1>Course Enrolment Form</h1>
|
||||
<p class="lead mb-0" style="font-size: 14px; opacity: 0.9;">Automobile Engineering Academy</p>
|
||||
<p class="lead mb-0 mt-2 fw-semibold" style="font-size: 15px; opacity: 0.95; color: var(--accent-yellow);">
|
||||
Automobile Engineering Academy
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container apply-area">
|
||||
|
||||
<div class="form-container-sm">
|
||||
<div class="form-card">
|
||||
<div class="form-header">
|
||||
<h2>
|
||||
<i class="fa-solid fa-file-circle-check me-2"></i>
|
||||
Course Enrolment Form
|
||||
New Student Registration
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="p-4">
|
||||
<form action="#" method="POST" enctype="multipart/form-data">
|
||||
<div class="p-4 p-md-5">
|
||||
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible fade show mb-4" role="alert">
|
||||
{{ session('success') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($errors->any())
|
||||
<div class="alert alert-danger mb-4">
|
||||
<ul class="mb-0">
|
||||
@foreach($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
<form action="{{ route('apply.store') }}" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
|
||||
{{-- STUDENT INFORMATION --}}
|
||||
|
|
@ -146,32 +194,32 @@
|
|||
<div class="row">
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">First Name <span class="required">*</span></label>
|
||||
<input type="text" name="first_name" class="form-control" required>
|
||||
<input type="text" name="first_name" class="form-control" placeholder="Enter your first name" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">Last Name <span class="required">*</span></label>
|
||||
<input type="text" name="last_name" class="form-control" required>
|
||||
<input type="text" name="last_name" class="form-control" placeholder="Enter your last name" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">NIC / Passport</label>
|
||||
<input type="text" name="nic" class="form-control">
|
||||
<label class="form-label">NIC / Passport Number</label>
|
||||
<input type="text" name="nic" class="form-control" placeholder="Identity Document No.">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">Nationality</label>
|
||||
<input type="text" name="nationality" class="form-control">
|
||||
<input type="text" name="nationality" class="form-control" placeholder="e.g. Sri Lankan">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">Address <span class="required">*</span></label>
|
||||
<input type="text" name="address" class="form-control" required>
|
||||
<label class="form-label">Residential Address <span class="required">*</span></label>
|
||||
<input type="text" name="address" class="form-control" placeholder="Street address" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">District / City / State <span class="required">*</span></label>
|
||||
<input type="text" name="state" class="form-control" required>
|
||||
<input type="text" name="state" class="form-control" placeholder="City or region" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
|
|
@ -198,17 +246,17 @@
|
|||
<div class="row">
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">Contact Number <span class="required">*</span></label>
|
||||
<input type="tel" name="mobile" class="form-control" required>
|
||||
<input type="tel" name="mobile" class="form-control" placeholder="Primary phone number" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">Alternative Contact Number</label>
|
||||
<input type="tel" name="mobile2" class="form-control">
|
||||
<input type="tel" name="mobile2" class="form-control" placeholder="Backup phone number">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">Email Address <span class="required">*</span></label>
|
||||
<input type="email" name="email" class="form-control" required>
|
||||
<input type="email" name="email" class="form-control" placeholder="name@example.com" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
|
|
@ -216,7 +264,7 @@
|
|||
<select name="preferred_contact_method" class="form-select">
|
||||
<option selected disabled>Select Your Option</option>
|
||||
<option value="email">Email</option>
|
||||
<option value="phone">Phone</option>
|
||||
<option value="phone">Phone Call</option>
|
||||
<option value="sms">SMS</option>
|
||||
</select>
|
||||
</div>
|
||||
|
|
@ -224,12 +272,12 @@
|
|||
|
||||
{{-- EDUCATION --}}
|
||||
<div class="section-title">
|
||||
<i class="fa-solid fa-graduation-cap me-2"></i> Education
|
||||
<i class="fa-solid fa-graduation-cap me-2"></i> Academic Qualifications
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">Still at school?</label>
|
||||
<label class="form-label">Are you currently a school student?</label>
|
||||
<select name="still_at_school" class="form-select">
|
||||
<option selected disabled>Select Your Option</option>
|
||||
<option value="Yes">Yes</option>
|
||||
|
|
@ -255,7 +303,7 @@
|
|||
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">School / College Name</label>
|
||||
<input type="text" name="school_name" class="form-control" placeholder="Enter School Name">
|
||||
<input type="text" name="school_name" class="form-control" placeholder="Enter last attended school name">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
|
|
@ -266,10 +314,10 @@
|
|||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">Examination Passed</label>
|
||||
<select name="exam_passed" class="form-select">
|
||||
<option selected disabled>Select Examination</option>
|
||||
<option selected disabled>Select Final Examination</option>
|
||||
<option value="G.C.E. O/L">G.C.E. O/L</option>
|
||||
<option value="G.C.E. A/L">G.C.E. A/L</option>
|
||||
<option value="NVQ">NVQ</option>
|
||||
<option value="NVQ">NVQ Standards</option>
|
||||
<option value="Certificate">Certificate</option>
|
||||
<option value="Diploma">Diploma</option>
|
||||
<option value="Degree">Degree</option>
|
||||
|
|
@ -278,17 +326,17 @@
|
|||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">Subjects</label>
|
||||
<input type="text" name="subjects" class="form-control" placeholder="e.g. Mathematics, Science">
|
||||
<label class="form-label">Core Subjects</label>
|
||||
<input type="text" name="subjects" class="form-control" placeholder="e.g. Mathematics, Science, Tech">
|
||||
</div>
|
||||
|
||||
<div class="col-12 mb-3-custom">
|
||||
<label class="form-label">Grades / Results</label>
|
||||
<textarea name="grades_results" class="form-control" rows="2" placeholder="Enter your grades or examination results"></textarea>
|
||||
<label class="form-label">Grades / Academic Results Summary</label>
|
||||
<textarea name="grades_results" class="form-control" rows="3" placeholder="List your relevant examination grades or index summaries..."></textarea>
|
||||
</div>
|
||||
|
||||
<div class="col-12 mb-3-custom">
|
||||
<label class="form-label">Educational Certificates</label>
|
||||
<label class="form-label">Upload Educational Certificates (Multiple Allowed)</label>
|
||||
<input type="file" name="certificates[]" class="form-control" accept=".pdf,.jpg,.jpeg,.png" multiple>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -301,24 +349,24 @@
|
|||
<div class="row">
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">Emergency Contact Name <span class="required">*</span></label>
|
||||
<input type="text" name="emergency_contact_name" class="form-control" required>
|
||||
<input type="text" name="emergency_contact_name" class="form-control" placeholder="Full name of guardian/relative" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3-custom">
|
||||
<label class="form-label">Relationship <span class="required">*</span></label>
|
||||
<input type="text" name="emergency_contact_relationship" class="form-control" required>
|
||||
<input type="text" name="emergency_contact_relationship" class="form-control" placeholder="e.g. Father, Mother, Spouse" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- TERMS AND CONDITIONS --}}
|
||||
<div class="form-check mb-3 mt-2">
|
||||
<div class="form-check mb-4 mt-3">
|
||||
<input class="form-check-input" type="checkbox" id="terms" required>
|
||||
<label class="form-check-label" for="terms" style="font-size: 13px;">
|
||||
I agree to the terms and conditions <span class="required">*</span>
|
||||
<label class="form-check-label fw-semibold" for="terms" style="font-size: 13px; color: #000; cursor: pointer;">
|
||||
I hereby declare that the details furnished above are true and correct to the best of my knowledge <span class="required">*</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<div class="mt-4">
|
||||
<button type="submit" class="submit-btn">Submit Application</button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -6,20 +6,29 @@
|
|||
|
||||
<style>
|
||||
:root{
|
||||
--primary:#5E244E;
|
||||
--secondary:#8B3A74;
|
||||
--light:#f8f4f7;
|
||||
/* Premium Modern Automotive Palette */
|
||||
--primary: #3E51B8; /* Tech Blue */
|
||||
--primary-light: #0a67df; /* Vibrant Electric Blue */
|
||||
--secondary: #BC1A1A; /* Deep Racing Red */
|
||||
--secondary-hover: #822424; /* Dark Burnt Red */
|
||||
--accent-dark: #753939; /* Muted Crimson */
|
||||
--bg-light: #F8FAFC; /* Soft slate light gray */
|
||||
|
||||
/* Semantic Adjustments */
|
||||
--text-main: #1E293B; /* Slate dark grey */
|
||||
--text-muted: #64748B; /* Neutral gray */
|
||||
--card-border: rgba(62, 81, 184, 0.1);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-family: 'Segoe UI', Arial, sans-serif;
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
.hero-contact{
|
||||
min-height:50vh;
|
||||
background:
|
||||
linear-gradient(rgba(0,0,0,.7),rgba(0,0,0,.7)),
|
||||
url('https://images.pexels.com/photos/3184465/pexels-photo-3184465.jpeg');
|
||||
linear-gradient(rgba(233, 236, 246, 0.6), rgba(39, 35, 35, 0.71)), url('https://images.pexels.com/photos/3184465/pexels-photo-3184465.jpeg');
|
||||
background-size:cover;
|
||||
background-position:center;
|
||||
display:flex;
|
||||
|
|
@ -33,37 +42,39 @@ body {
|
|||
background:#fff;
|
||||
border-radius:20px;
|
||||
padding:35px;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,.05);
|
||||
border: 1px solid #efeff4;
|
||||
box-shadow: 0 10px 30px rgba(0,0,0,.04);
|
||||
border: 1px solid var(--card-border);
|
||||
}
|
||||
|
||||
.form-control{
|
||||
border-radius:10px;
|
||||
padding:12px;
|
||||
border: 1px solid #ced4da;
|
||||
border: 1px solid #cbd5e1;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 0 0 0.25rem rgba(94, 36, 78, 0.25);
|
||||
border-color: var(--primary-light);
|
||||
box-shadow: 0 0 0 4px rgba(10, 103, 223, 0.15);
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.btn-contact{
|
||||
background:var(--primary);
|
||||
background: #6a2525 ;
|
||||
color:#fff;
|
||||
border-radius:10px;
|
||||
padding:12px 30px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
box-shadow: 0 4px 12px rgba(62, 81, 184, 0.2);
|
||||
}
|
||||
|
||||
.btn-contact:hover{
|
||||
background:var(--secondary);
|
||||
background: linear-gradient(135deg, var(--secondary) 0%, var(--secondary-hover) 100%);
|
||||
color:#fff;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 5px 15px rgba(94, 36, 78, 0.3);
|
||||
box-shadow: 0 6px 15px rgba(188, 26, 26, 0.3);
|
||||
}
|
||||
|
||||
.info-card{
|
||||
|
|
@ -72,19 +83,23 @@ body {
|
|||
padding:20px;
|
||||
text-align:center;
|
||||
box-shadow: 0 5px 20px rgba(0,0,0,.04);
|
||||
border: 1px solid #efeff4;
|
||||
border: 1px solid var(--card-border);
|
||||
transition:.3s;
|
||||
}
|
||||
|
||||
.info-card:hover{
|
||||
transform:translateY(-5px);
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 10px 25px rgba(94, 36, 78, 0.08);
|
||||
border-color: var(--primary-light);
|
||||
box-shadow: 0 10px 25px rgba(62, 81, 184, 0.1);
|
||||
}
|
||||
|
||||
|
||||
.info-card i {
|
||||
color: var(--primary) !important;
|
||||
color: #861E28 !important;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.info-card:hover i {
|
||||
color: var(--secondary) !important;
|
||||
}
|
||||
|
||||
/* ========================================================
|
||||
|
|
@ -96,17 +111,14 @@ body {
|
|||
transition: all 0.8s cubic-bezier(0.25, 1, 0.5, 1);
|
||||
}
|
||||
|
||||
|
||||
.fade-up-init {
|
||||
transform: translateY(30px);
|
||||
}
|
||||
|
||||
|
||||
.slide-left-init {
|
||||
transform: translateX(-40px);
|
||||
}
|
||||
|
||||
|
||||
.fade-in-init {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
|
@ -123,7 +135,7 @@ body {
|
|||
<div class="container">
|
||||
<div class="animate-item animated fade-up-init">
|
||||
<h1 class="fw-bold display-4">Contact Us</h1>
|
||||
<p class="fs-5">We are here to help you. Reach us anytime.</p>
|
||||
<p class="fs-5 text-white-50" style="color:rgba(255, 255, 255, 0.8) !important">We are here to help you. Reach us anytime.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -138,9 +150,7 @@ body {
|
|||
<div class="col-md-6 animate-item slide-left-init">
|
||||
<div class="contact-box">
|
||||
|
||||
<h3 class="mb-4 fw-bold" style="color: #1c1d1f;">Send Message</h3>
|
||||
|
||||
|
||||
<h3 class="mb-4 fw-bold" style="color: var(--text-main);">Send Message</h3>
|
||||
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success">
|
||||
|
|
@ -148,27 +158,26 @@ body {
|
|||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
<form action="{{ route('contact.store') }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Name</label>
|
||||
<label class="form-label fw-semibold text-secondary-emphasis">Name</label>
|
||||
<input type="text" name="name" class="form-control" placeholder="Your Name" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Email</label>
|
||||
<label class="form-label fw-semibold text-secondary-emphasis">Email</label>
|
||||
<input type="email" name="email" class="form-control" placeholder="Your Email" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Subject</label>
|
||||
<label class="form-label fw-semibold text-secondary-emphasis">Subject</label>
|
||||
<input type="text" name="subject" class="form-control" placeholder="Subject" required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Message</label>
|
||||
<label class="form-label fw-semibold text-secondary-emphasis">Message</label>
|
||||
<textarea name="message" rows="5" class="form-control" placeholder="Your Message" required></textarea>
|
||||
</div>
|
||||
|
||||
|
|
@ -181,7 +190,7 @@ Send Message
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Info Cards -->
|
||||
<div class="col-md-6 animate-item fade-in-init">
|
||||
|
||||
<div class="info-card mb-3">
|
||||
|
|
@ -217,37 +226,17 @@ Send Message
|
|||
|
||||
<!-- MAP -->
|
||||
<section class="pb-5">
|
||||
<div class="container">
|
||||
|
||||
<!-- <iframe
|
||||
src="https://www.google.com/maps/embed/v1/place?key=YOUR_API_KEY&q=place_id:ChIJXdB3Sy_84joRYNze2w86UjQ"
|
||||
width="100%"
|
||||
height="300"
|
||||
style="border:0;border-radius:15px;"
|
||||
allowfullscreen=""
|
||||
loading="lazy">
|
||||
</iframe> -->
|
||||
|
||||
<div class="container animate-item fade-up-init">
|
||||
<iframe
|
||||
src="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d989.8732851214081!2d80.0435697!3d7.0771955!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x3ae2fc2f4b77d05d%3A0x34523a0fdbdedc60!2sGlitz%20Park!5e0!3m2!1sen!2slk!4v1719999999999!5m2!1sen!2slk"
|
||||
width="100%"
|
||||
height="300"
|
||||
style="border:0;border-radius:15px;"
|
||||
allowfullscreen=""
|
||||
loading="lazy">
|
||||
</iframe>
|
||||
<!-- <section class="pb-5">
|
||||
<div class="container animate-item fade-up-init">
|
||||
<iframe
|
||||
src="https://www.google.com/maps/embed/pb=!1m14!1m8!1m3!1d989.8732851214081!2d80.0435697!3d7.0771955!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x3ae2fc2f4b77d05d%3A0x34523a0fdbdedc60!2sGlitz%20Park!5e0!3m2!1sen!2slk!4v1719999999999!5m2!1sen!2slk"
|
||||
width="100%"
|
||||
height="350"
|
||||
style="border:0;border-radius:20px; box-shadow: 0 10px 30px rgba(0,0,0,.05);"
|
||||
style="border:0;border-radius:20px; box-shadow: 0 10px 30px rgba(0,0,0,.04); border: 1px solid var(--card-border);"
|
||||
allowfullscreen=""
|
||||
loading="lazy">
|
||||
</iframe>
|
||||
</div>
|
||||
</section> -->
|
||||
</section>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
|
|
@ -267,5 +256,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||
animatedElements.forEach(el => observer.observe(el));
|
||||
});
|
||||
</script>
|
||||
|
|
||||
|
||||
|
||||
@endsection
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,437 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<title>Password Recovery</title>
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
|
||||
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background: #f4f6f9;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
.container-box {
|
||||
background: #ffffff;
|
||||
width: 100%;
|
||||
max-width: 420px;
|
||||
border-radius: 16px;
|
||||
padding: 40px 36px;
|
||||
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.icon-wrap {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
background: #943835e3;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 20px;
|
||||
}
|
||||
.icon-wrap i { font-size: 24px; color: #eeff8f; }
|
||||
h1 { font-size: 22px; color: #1f2937; text-align: center; margin-bottom: 8px; font-weight: 700; }
|
||||
p.subtitle { text-align: center; color: #6b7280; font-size: 14px; margin-bottom: 28px; line-height: 1.5; }
|
||||
.form-group { margin-bottom: 20px; position: relative; }
|
||||
label { display: block; font-size: 13px; font-weight: 600; color: #374151; margin-bottom: 6px; }
|
||||
input[type="email"], input[type="text"], input[type="password"] {
|
||||
width: 100%; padding: 12px 14px; border: 1.5px solid #e5e7eb;
|
||||
border-radius: 10px; font-size: 14px; color: #1f2937; outline: none;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
input:focus { border-color: #943835e3; box-shadow: 0 0 0 3px rgba(148, 56, 53, 0.15); }
|
||||
.toggle-password { position: absolute; right: 14px; top: 38px; cursor: pointer; color: #6b7280; }
|
||||
.err, .error { color: #dc2626; font-size: 12.5px; margin-top: 6px; display: block; }
|
||||
.otp-input { letter-spacing: 4px; text-align: center; font-size: 20px; font-weight: 700; }
|
||||
button[type="submit"] {
|
||||
width: 100%; padding: 13px; background: #943835e3; color: #fff;
|
||||
border: none; border-radius: 10px; font-size: 15px; font-weight: 600;
|
||||
cursor: pointer; margin-top: 10px; transition: transform 0.15s ease;
|
||||
}
|
||||
button[type="submit"]:hover { transform: translateY(-1px); box-shadow: 0 8px 20px rgba(148, 56, 53, 0.35); }
|
||||
button[type="submit"]:disabled { background: #94383580; cursor: not-allowed; }
|
||||
.back-link { display: block; text-align: center; margin-top: 22px; font-size: 13.5px; color: #6b7280; }
|
||||
.back-link a { color: #231d77e3; font-weight: 600; text-decoration: none; }
|
||||
.powered { text-align: center; margin-top: 20px; font-size: 12px; color: #9ca3af; }
|
||||
|
||||
.otp-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.otp-box {
|
||||
width: 48px;
|
||||
height: 52px;
|
||||
text-align: center;
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
border: 1.5px solid #e5e7eb;
|
||||
border-radius: 10px;
|
||||
outline: none;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.otp-box:focus {
|
||||
border-color: #943835e3;
|
||||
box-shadow: 0 0 0 3px rgba(148, 56, 53, 0.15);
|
||||
}
|
||||
|
||||
.success-icon-wrap {
|
||||
font-size: 60px;
|
||||
color: #10b981; /* Green color */
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.login-btn-link {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 13px;
|
||||
background: #943835e3;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
border-radius: 10px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
margin-top: 20px;
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
|
||||
.login-btn-link:hover {
|
||||
color: #fff;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 8px 20px rgba(148, 56, 53, 0.35);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container-box">
|
||||
<div class="icon-wrap" id="main-icon">
|
||||
<i class="fa-solid fa-key"></i>
|
||||
</div>
|
||||
|
||||
<!-- Step 1: Email Form -->
|
||||
<form class="login-form" name="login-form" action="{{ route('password.email') }}" method="post" id="login-form">
|
||||
@csrf
|
||||
<h1>Recover Password</h1>
|
||||
<p class="subtitle">Enter your registered email address to receive an OTP code.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="email-login">Email Address</label>
|
||||
<input type="email" name="email" id="email-login" placeholder="name@example.com" required>
|
||||
<span id="email-err" class="err"></span>
|
||||
@if ($errors->has('email'))
|
||||
<span class="err">{{ $errors->first('email') }}</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<button type="submit" id="verify-btn" onclick="validateEmail(event)">Verify Email</button>
|
||||
|
||||
<div class="back-link">
|
||||
Remember the password? <a href="/signin">Please Login</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Step 2: OTP Verification Form -->
|
||||
<div id="otp_sec" style="display: none;">
|
||||
<h1>Enter OTP Code</h1>
|
||||
<p class="subtitle">Please check your email and enter the 6-digit verification code.</p>
|
||||
|
||||
<form name="emailOtpForm" id="emailOtpForm">
|
||||
@csrf
|
||||
<div class="form-group">
|
||||
<label>Verification Code</label>
|
||||
|
||||
<div class="otp-container">
|
||||
<input type="text" class="otp-box" maxlength="1" pattern="\d*" inputmode="numeric" required>
|
||||
<input type="text" class="otp-box" maxlength="1" pattern="\d*" inputmode="numeric" required>
|
||||
<input type="text" class="otp-box" maxlength="1" pattern="\d*" inputmode="numeric" required>
|
||||
<input type="text" class="otp-box" maxlength="1" pattern="\d*" inputmode="numeric" required>
|
||||
<input type="text" class="otp-box" maxlength="1" pattern="\d*" inputmode="numeric" required>
|
||||
<input type="text" class="otp-box" maxlength="1" pattern="\d*" inputmode="numeric" required>
|
||||
</div>
|
||||
<input type="hidden" id="otp" name="otpm">
|
||||
|
||||
<span id="otpm_err" class="err"></span>
|
||||
</div>
|
||||
|
||||
<button type="submit" onclick="showPassword(event)">Submit Code</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Step 3: Password Reset Form -->
|
||||
<div id="password_sec" style="display: none;">
|
||||
<h1>Reset Password</h1>
|
||||
<p class="subtitle">Create a new password for your account.</p>
|
||||
|
||||
<form class="login-form" name="reset-password-form" id="reset-password-form" action="{{ route('password.update') }}" method="post" onsubmit="handlePasswordReset(event)">
|
||||
@csrf
|
||||
<input type="hidden" name="email" value="" id="hidden_email">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password-m">New Password</label>
|
||||
<input type="password" name="password_mo" id="password-m" placeholder="••••••••" required>
|
||||
<i class="fa-solid fa-eye toggle-password" id="view1" onclick="togglePassword('password-m', 'view1', 'no-view1')"></i>
|
||||
<i class="fa-solid fa-eye-slash toggle-password" id="no-view1" onclick="togglePassword('password-m', 'view1', 'no-view1')" style="display:none;"></i>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="confirm_password">Confirm Password</label>
|
||||
<input type="password" name="password_mo_confirmation" id="confirm_password" placeholder="••••••••" required>
|
||||
<i class="fa-solid fa-eye toggle-password" id="view-con1" onclick="togglePassword('confirm_password', 'view-con1', 'no-view-con1')"></i>
|
||||
<i class="fa-solid fa-eye-slash toggle-password" id="no-view-con1" onclick="togglePassword('confirm_password', 'view-con1', 'no-view-con1')" style="display:none;"></i>
|
||||
<span id="con-pass-err" class="error"></span>
|
||||
</div>
|
||||
|
||||
<button type="submit" id="reset-btn">Reset Password</button>
|
||||
|
||||
<div class="back-link">
|
||||
Remember password? <a href="/signin">Please Login</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Step 4: Success Message Screen -->
|
||||
<div id="success_sec" style="display: none; text-align: center;">
|
||||
<div class="success-icon-wrap">
|
||||
<i class="fa-solid fa-circle-check"></i>
|
||||
</div>
|
||||
<h1>Password Reset Successful!</h1>
|
||||
<p class="subtitle">Your password has been reset successfully. You can now log in with your new password.</p>
|
||||
|
||||
<a href="/signin" class="login-btn-link">Proceed to Login</a>
|
||||
</div>
|
||||
|
||||
<p class="powered">Powered by <a href="#" style="color: #6b7280; text-decoration: none; font-weight: 600;">GPiT</a></p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function validateEmail(event) {
|
||||
event.preventDefault();
|
||||
|
||||
var email = document.getElementById('email-login').value;
|
||||
var emailErr = document.getElementById('email-err');
|
||||
var csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
||||
var verifyBtn = document.getElementById('verify-btn');
|
||||
|
||||
emailErr.textContent = '';
|
||||
|
||||
if (email.trim() === '') {
|
||||
emailErr.textContent = 'Please enter your email';
|
||||
return;
|
||||
}
|
||||
|
||||
verifyBtn.disabled = true;
|
||||
verifyBtn.textContent = 'Please Wait...';
|
||||
|
||||
fetch("{{ route('password.email') }}", {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'X-CSRF-TOKEN': csrfToken
|
||||
},
|
||||
body: JSON.stringify({ email: email })
|
||||
})
|
||||
.then(async response => {
|
||||
const text = await response.text();
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
} catch (e) {
|
||||
console.error("SERVER ERROR DETAILS:", text);
|
||||
throw new Error("Server returned HTML response instead of JSON.");
|
||||
}
|
||||
})
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
document.getElementById("hidden_email").value = email;
|
||||
document.getElementById("login-form").style.display = "none";
|
||||
document.getElementById("otp_sec").style.display = "block";
|
||||
} else {
|
||||
if (data.errors && data.errors.email) {
|
||||
emailErr.textContent = data.errors.email[0];
|
||||
} else {
|
||||
emailErr.textContent = data.message || 'Email not found in our records.';
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
emailErr.textContent = 'An error occurred. Check browser console (F12) for details.';
|
||||
})
|
||||
.finally(() => {
|
||||
verifyBtn.disabled = false;
|
||||
verifyBtn.textContent = 'Verify Email';
|
||||
});
|
||||
}
|
||||
|
||||
function showPassword(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const otp = document.getElementById('otp').value;
|
||||
const otpm_err = document.getElementById('otpm_err');
|
||||
const token = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
||||
|
||||
otpm_err.innerText = '';
|
||||
|
||||
if (otp.trim() === '' || otp.length < 6) {
|
||||
otpm_err.innerText = 'Please enter a valid 6-digit OTP code.';
|
||||
return;
|
||||
}
|
||||
|
||||
fetch("{{ route('password.verify.otp') }}", {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': token
|
||||
},
|
||||
body: JSON.stringify({ otp: otp })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
document.getElementById("otp_sec").style.display = "none";
|
||||
document.getElementById("password_sec").style.display = "block";
|
||||
} else {
|
||||
otpm_err.innerText = data.message || 'Invalid OTP code';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
otpm_err.innerText = 'Verification failed. Try again.';
|
||||
});
|
||||
}
|
||||
|
||||
function handlePasswordReset(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const form = document.getElementById('reset-password-form');
|
||||
const formData = new FormData(form);
|
||||
const resetBtn = document.getElementById('reset-btn');
|
||||
const passErr = document.getElementById('con-pass-err');
|
||||
|
||||
const pass = document.getElementById('password-m').value;
|
||||
const confirmPass = document.getElementById('confirm_password').value;
|
||||
|
||||
if (pass !== confirmPass) {
|
||||
passErr.innerText = "Passwords do not match!";
|
||||
passErr.style.color = "#dc2626";
|
||||
return;
|
||||
}
|
||||
|
||||
resetBtn.disabled = true;
|
||||
resetBtn.textContent = 'Resetting...';
|
||||
|
||||
fetch(form.action, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
body: formData
|
||||
})
|
||||
.then(async response => {
|
||||
const data = await response.json();
|
||||
if (response.ok || data.success) {
|
||||
|
||||
document.getElementById("main-icon").style.display = "none";
|
||||
document.getElementById("password_sec").style.display = "none";
|
||||
document.getElementById("success_sec").style.display = "block";
|
||||
} else {
|
||||
passErr.innerText = data.message || 'Failed to reset password.';
|
||||
passErr.style.color = "#dc2626";
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
// Unexpected redirect/success response handling
|
||||
document.getElementById("main-icon").style.display = "none";
|
||||
document.getElementById("password_sec").style.display = "none";
|
||||
document.getElementById("success_sec").style.display = "block";
|
||||
})
|
||||
.finally(() => {
|
||||
resetBtn.disabled = false;
|
||||
resetBtn.textContent = 'Reset Password';
|
||||
});
|
||||
}
|
||||
|
||||
$('#password-m, #confirm_password').on('keyup', function() {
|
||||
if ($('#password-m').val() !== '' && $('#password-m').val() === $('#confirm_password').val()) {
|
||||
$('#con-pass-err').html('Passwords match').css('color', '#047857');
|
||||
} else if ($('#confirm_password').val() !== '') {
|
||||
$('#con-pass-err').html('Passwords do not match').css('color', '#dc2626');
|
||||
}
|
||||
});
|
||||
|
||||
function togglePassword(inputId, eyeId, eyeSlashId) {
|
||||
var field = document.getElementById(inputId);
|
||||
var eye = document.getElementById(eyeId);
|
||||
var eyeSlash = document.getElementById(eyeSlashId);
|
||||
|
||||
if (field.type === "password") {
|
||||
field.type = "text";
|
||||
eye.style.display = "none";
|
||||
eyeSlash.style.display = "block";
|
||||
} else {
|
||||
field.type = "password";
|
||||
eye.style.display = "block";
|
||||
eyeSlash.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const inputs = document.querySelectorAll(".otp-box");
|
||||
const hiddenOtpInput = document.getElementById("otp");
|
||||
|
||||
inputs.forEach((input, index) => {
|
||||
input.addEventListener("input", (e) => {
|
||||
input.value = input.value.replace(/\D/g, '');
|
||||
|
||||
if (input.value && index < inputs.length - 1) {
|
||||
inputs[index + 1].focus();
|
||||
}
|
||||
updateHiddenOtp();
|
||||
});
|
||||
|
||||
input.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Backspace" && !input.value && index > 0) {
|
||||
inputs[index - 1].focus();
|
||||
}
|
||||
});
|
||||
|
||||
input.addEventListener("paste", (e) => {
|
||||
e.preventDefault();
|
||||
const pasteData = e.clipboardData.getData("text").trim().replace(/\D/g, '');
|
||||
if (pasteData.length === 6) {
|
||||
pasteData.split("").forEach((char, i) => {
|
||||
if (inputs[i]) inputs[i].value = char;
|
||||
});
|
||||
inputs[5].focus();
|
||||
updateHiddenOtp();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function updateHiddenOtp() {
|
||||
let fullOtp = "";
|
||||
inputs.forEach(input => fullOtp += input.value);
|
||||
hiddenOtpInput.value = fullOtp;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,466 @@
|
|||
<!-- feedback controller function -->
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- use Illuminate\Http\Request;
|
||||
use App\Models\Feedback;
|
||||
use App\Models\user; -->
|
||||
|
||||
|
||||
|
||||
<!-- // public function feedback(Request $request)
|
||||
// {
|
||||
|
||||
// $request->validate([
|
||||
// 'feedback_type' => 'required',
|
||||
// 'subject' => 'required|string|max:255',
|
||||
// 'feedback_text' => 'required|string',
|
||||
// ]);
|
||||
|
||||
|
||||
// Feedback::create([
|
||||
// 'student_id' => auth()->id(),
|
||||
// 'feedback_type' => $request->feedback_type,
|
||||
// 'subject' => $request->subject,
|
||||
// 'feedback_text' => $request->feedback_text,
|
||||
// 'status' => 'Pending',
|
||||
// ]);
|
||||
|
||||
// return redirect()->back()->with('success', 'Feedback submitted successfully!');
|
||||
// }
|
||||
|
||||
|
||||
// public function feedback(Request $request)
|
||||
// {
|
||||
// $request->validate([
|
||||
// 'feedback_type' => 'required',
|
||||
// 'subject' => 'required|string|max:255',
|
||||
// 'feedback_text' => 'required|string',
|
||||
// ]);
|
||||
|
||||
|
||||
// $studentLogId = session('student_portal_log_id');
|
||||
|
||||
|
||||
// if (!$studentLogId) {
|
||||
// return redirect('/students')->with('error', 'Please login first to submit feedback!');
|
||||
// }
|
||||
|
||||
// Feedback::create([
|
||||
// 'student_id' => $studentLogId,
|
||||
// 'feedback_type' => $request->feedback_type,
|
||||
// 'subject' => $request->subject,
|
||||
// 'feedback_text' => $request->feedback_text,
|
||||
// 'status' => 'Pending',
|
||||
// ]);
|
||||
|
||||
// return redirect('/Feedback&Complain')->back()->with('success', 'Feedback submitted successfully!');}
|
||||
// -->
|
||||
|
||||
|
||||
########### ########### ########### ########### ########### ########### ########### ###########
|
||||
|
||||
|
||||
<!-- js table data view -->
|
||||
|
||||
|
||||
<!-- JavaScript to handle Submissions -->
|
||||
<!-- <script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const tableBody = document.getElementById('historyTableBody');
|
||||
|
||||
|
||||
function getFormattedDate() {
|
||||
const options = { day: '2-digit', month: 'long', year: 'numeric' };
|
||||
return new Date().toLocaleDateString('en-GB', options);
|
||||
}
|
||||
|
||||
|
||||
document.getElementById('feedbackForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const subject = document.getElementById('feedbackSubject').value;
|
||||
const date = getFormattedDate();
|
||||
|
||||
|
||||
const newRow = document.createElement('tr');
|
||||
newRow.innerHTML = `
|
||||
<td>Feedback</td>
|
||||
<td>${subject}</td>
|
||||
<td>${date}</td>
|
||||
<td><span class="badge-status pending"> Pending </span></td>
|
||||
`;
|
||||
|
||||
|
||||
tableBody.insertBefore(newRow, tableBody.firstChild);
|
||||
|
||||
|
||||
this.reset();
|
||||
alert('Feedback submitted successfully!');
|
||||
});
|
||||
|
||||
// 2. Complaint Form Submission
|
||||
document.getElementById('complaintForm').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const title = document.getElementById('complaintTitle').value;
|
||||
const date = getFormattedDate();
|
||||
|
||||
const newRow = document.createElement('tr');
|
||||
newRow.innerHTML = `
|
||||
<td>Complaint</td>
|
||||
<td>${title}</td>
|
||||
<td>${date}</td>
|
||||
<td><span class="badge-status pending"> Pending </span></td>
|
||||
`;
|
||||
|
||||
tableBody.insertBefore(newRow, tableBody.firstChild);
|
||||
|
||||
this.reset();
|
||||
alert('Complaint submitted successfully!');
|
||||
});
|
||||
});
|
||||
</script> -->
|
||||
|
||||
|
||||
|
||||
########### ########### ########### ########### ########### ########### ########### ###########
|
||||
|
||||
<!-- student view profile blade -->
|
||||
|
||||
|
||||
|
||||
<!-- @extends('layouts.studentportalnav')
|
||||
|
||||
@section('title', 'Student Profile')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
|
||||
body{
|
||||
background:#f6f7fb;
|
||||
}
|
||||
|
||||
|
||||
/* Header */
|
||||
|
||||
.profile-header{
|
||||
|
||||
background:linear-gradient(135deg,#5E244E,#4a1c3e);
|
||||
color:#fff;
|
||||
border-radius:20px;
|
||||
padding:40px;
|
||||
margin-bottom:35px;
|
||||
box-shadow:0 15px 35px rgba(0,0,0,.15);
|
||||
|
||||
}
|
||||
|
||||
|
||||
.profile-header h2{
|
||||
|
||||
font-weight:700;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.profile-header p{
|
||||
|
||||
color:#ddd;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Profile Card */
|
||||
|
||||
.profile-card{
|
||||
|
||||
background:#fff;
|
||||
border-radius:20px;
|
||||
padding:30px;
|
||||
box-shadow:0 10px 30px rgba(0,0,0,.08);
|
||||
height:100%;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Student Image */
|
||||
|
||||
.profile-image{
|
||||
|
||||
width:150px;
|
||||
height:150px;
|
||||
border-radius:50%;
|
||||
object-fit:cover;
|
||||
border:6px solid #d4af37;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.student-name{
|
||||
|
||||
color:#5E244E;
|
||||
font-weight:700;
|
||||
margin-top:15px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.student-id{
|
||||
|
||||
background:#5E244E;
|
||||
color:#fff;
|
||||
padding:8px 20px;
|
||||
border-radius:50px;
|
||||
display:inline-block;
|
||||
font-size:14px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Information */
|
||||
|
||||
.info-title{
|
||||
|
||||
color:#5E244E;
|
||||
font-weight:700;
|
||||
border-bottom:2px solid #d4af37;
|
||||
padding-bottom:10px;
|
||||
margin-bottom:20px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.info-row{
|
||||
|
||||
display:flex;
|
||||
justify-content:space-between;
|
||||
padding:12px 0;
|
||||
border-bottom:1px solid #eee;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.label{
|
||||
|
||||
color:#777;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.value{
|
||||
|
||||
font-weight:600;
|
||||
color:#333;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Course */
|
||||
|
||||
.course-box{
|
||||
|
||||
background:#5E244E;
|
||||
color:#fff;
|
||||
padding:25px;
|
||||
border-radius:20px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.course-box h4{
|
||||
|
||||
color:#d4af37;
|
||||
font-weight:700;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.course-item{
|
||||
|
||||
margin-top:12px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.course-item i{
|
||||
|
||||
color:#d4af37;
|
||||
width:25px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Button */
|
||||
|
||||
.edit-btn{
|
||||
|
||||
background:#d4af37;
|
||||
color:white;
|
||||
border:none;
|
||||
border-radius:50px;
|
||||
padding:12px 30px;
|
||||
font-weight:600;
|
||||
|
||||
}
|
||||
|
||||
|
||||
.edit-btn:hover{
|
||||
|
||||
background:#c49d20;
|
||||
color:#fff;
|
||||
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
<div class="container py-4">
|
||||
|
||||
|
||||
Header -->
|
||||
|
||||
<!-- <div class="profile-header">
|
||||
<h2> <i class="fas fa-user-graduate"></i>Student Profile </h2>
|
||||
<p>Manage your personal information and academic details. </p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-4">
|
||||
<div class="profile-card text-center">
|
||||
|
||||
<img src="{{ !empty($student->image) ? asset($student->image) : 'https://i.pravatar.cc/300' }}"
|
||||
class="profile-image" alt="Profile Image">
|
||||
|
||||
<h3 class="student-name">{{ $student->full_name }}</h3>
|
||||
|
||||
<span class="student-id">
|
||||
Student ID : {{ $student->student_id }}
|
||||
</span>
|
||||
<hr>
|
||||
|
||||
<button class="edit-btn mt-3">
|
||||
<i class="fas fa-edit"></i> Edit Profile
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Details -->
|
||||
<!-- <div class="col-lg-8">
|
||||
<div class="profile-card">
|
||||
<h4 class="info-title">
|
||||
<i class="fas fa-user"></i>
|
||||
Personal Information
|
||||
</h4>
|
||||
|
||||
<div class="info-row">
|
||||
<span class="label">Full Name</span>
|
||||
<span class="value">{{ $student->full_name }}</span>
|
||||
</div>
|
||||
|
||||
<div class="info-row">
|
||||
<span class="label">NIC / Passport</span>
|
||||
<span class="value">{{ $student->nic_passport }}</span>
|
||||
</div>
|
||||
|
||||
<div class="info-row">
|
||||
<span class="label">Date of Birth</span>
|
||||
<span class="value">
|
||||
{{ date('d F Y', strtotime($student->date_of_birth)) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="info-row">
|
||||
<span class="label">Gender</span>
|
||||
<span class="value">{{ $student->gender }}</span>
|
||||
</div>
|
||||
|
||||
<div class="info-row">
|
||||
<span class="label">Email</span>
|
||||
<span class="value">{{ $student->email }}</span>
|
||||
</div>
|
||||
|
||||
<div class="info-row">
|
||||
<span class="label">Phone</span>
|
||||
<span class="value">{{ $student->phone }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4 mt-1"> -->
|
||||
<!-- Education -->
|
||||
<!-- <div class="col-lg-6">
|
||||
<div class="profile-card">
|
||||
<h4 class="info-title">
|
||||
<i class="fas fa-graduation-cap"></i>
|
||||
Educational Background
|
||||
</h4>
|
||||
<div class="info-row">
|
||||
<span class="label">Qualification</span>
|
||||
<span class="value">{{ $student->qualification }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">Institute</span>
|
||||
<span class="value">{{ $student->institute }}</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="label">Year Completed</span>
|
||||
<span class="value">{{ $student->year_completed }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- Course Details -->
|
||||
<!-- <div class="col-lg-6">
|
||||
<div class="course-box">
|
||||
<h4><i class="fas fa-car"></i>Course Details</h4>
|
||||
|
||||
<div class="course-item">
|
||||
<i class="fas fa-book"></i> {{ $student->course_name }}
|
||||
</div>
|
||||
<div class="course-item">
|
||||
<i class="fas fa-calendar"></i> Duration : {{ $student->duration }}
|
||||
</div>
|
||||
<div class="course-item">
|
||||
<i class="fas fa-layer-group"></i> Current Semester : {{ $student->current_semester }}
|
||||
</div>
|
||||
<div class="course-item">
|
||||
<i class="fas fa-user-tie"></i> Trainer : {{ $student->trainer_name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@endsection -->
|
||||
|
||||
########### ########### ########### ########### ########### ########### ########### ###########
|
||||
|
||||
<!-- // Home Page
|
||||
Route::get('/', function () {
|
||||
return view('welcome');
|
||||
});
|
||||
|
||||
|
||||
// Route::get('/StudentProfile', [studentsController::class, 'showProfile'])->name('StudentProfile');
|
||||
|
||||
Route::post('/studentlogout', [studentportalnavController::class, 'logout']);
|
||||
|
||||
// Route::post('/feedback', [FeedbackController ::class, 'feedback'])->name('feedback.store'); -->
|
||||
<!--
|
||||
Route::post('/feedback/store', [FeedbackController::class, 'feedback']) ->middleware('auth') ->name('feedback.store');
|
||||
|
||||
|
||||
Route::post('/contact-submit', [ContactMsgController::class, 'store'])->name('contact.store'); -->
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,368 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<title>@yield('title', 'Admin Portal - Automobile Academic')</title>
|
||||
|
||||
<!-- Font Awesome Icons & Bootstrap 5 -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" integrity="sha512-Kc323vGBEqzTmouAECnVceyQqyqdsSiqLQISBL29aUW4U/M7pSPA/gEUZQqv1cwx4OnYxTxve5UMg5GT6L4JJg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--theme-navy: #2D355B;
|
||||
--theme-footer-navy: #1F2541;
|
||||
--theme-red: #822424;
|
||||
--theme-red-hover: #df2c3e;
|
||||
--theme-yellow: #FFEA85;
|
||||
--theme-bg: #F6F6F6;
|
||||
--sidebar-width: 260px;
|
||||
--text-dark: #333333;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--theme-bg);
|
||||
color: var(--text-dark);
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: var(--sidebar-width);
|
||||
height: 100vh;
|
||||
background: var(--theme-navy);
|
||||
color: #fff;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 24px 0;
|
||||
transition: all 0.3s ease;
|
||||
z-index: 1030;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 2px 0 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.sidebar .brand {
|
||||
padding: 0 24px 20px;
|
||||
font-weight: 700;
|
||||
font-size: 1.25rem;
|
||||
color: #ffffff;
|
||||
border-bottom: 1px solid rgba(255,255,255,.15);
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sidebar .admin-badge {
|
||||
background-color: var(--theme-red);
|
||||
font-size: 0.7rem;
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
margin-left: 8px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.sidebar .nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sidebar .nav-link {
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
padding: 14px 24px;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
transition: all 0.2s ease;
|
||||
border-left: 4px solid transparent;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sidebar .nav-link i {
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sidebar .nav-link:hover {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
color: var(--theme-yellow) !important;
|
||||
padding-left: 28px;
|
||||
}
|
||||
|
||||
.sidebar .nav-link.active {
|
||||
background: var(--theme-footer-navy);
|
||||
color: var(--theme-yellow) !important;
|
||||
border-left: 4px solid #F73F52;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.sidebar-user-profile {
|
||||
padding: 15px 24px;
|
||||
border-top: 1px solid rgba(255,255,255,.15);
|
||||
margin-top: auto;
|
||||
background: var(--theme-footer-navy);
|
||||
}
|
||||
|
||||
.sidebar-user-profile .user-dropdown-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-size: 0.95rem;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.sidebar-user-profile .user-dropdown-toggle:hover {
|
||||
color: var(--theme-yellow);
|
||||
}
|
||||
|
||||
.main {
|
||||
margin-left: var(--sidebar-width);
|
||||
width: calc(100% - var(--sidebar-width));
|
||||
min-height: 100vh;
|
||||
padding: 40px;
|
||||
background: var(--theme-bg);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.mobile-header {
|
||||
display: none;
|
||||
background: var(--theme-navy);
|
||||
color: #ffffff;
|
||||
padding: 12px 20px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1020;
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.4rem;
|
||||
cursor: pointer;
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sidebar-toggle:hover {
|
||||
color: var(--theme-yellow);
|
||||
}
|
||||
|
||||
.mobile-brand {
|
||||
font-weight: 700;
|
||||
font-size: 1.1rem;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.sidebar-overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 1025;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.sidebar-overlay.show {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
.sidebar {
|
||||
left: calc(-1 * var(--sidebar-width));
|
||||
}
|
||||
|
||||
.sidebar.show {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.main {
|
||||
margin-left: 0;
|
||||
padding: 85px 20px 20px 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mobile-header {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Mobile Top Navigation Bar -->
|
||||
<header class="mobile-header">
|
||||
<button class="sidebar-toggle" id="toggleBtn" aria-label="Toggle Sidebar">
|
||||
<i class="fa-solid fa-bars"></i>
|
||||
</button>
|
||||
<div class="mobile-brand">
|
||||
<i class="fa-solid fa-user-shield me-1"></i> Admin Panel
|
||||
</div>
|
||||
|
||||
<div class="mobile-user-profile">
|
||||
@if(session()->has('admin_id'))
|
||||
<div class="dropdown">
|
||||
<a class="text-white text-decoration-none dropdown-toggle d-flex flex-column align-items-center justify-content-center gap-0" href="#" role="button" id="userMenuMobile" data-bs-toggle="dropdown" aria-expanded="false" style="line-height: 1.1;">
|
||||
<i class="fa-solid fa-circle-user" style="font-size: 24px; color: var(--theme-yellow);"></i>
|
||||
<span class="fst-italic" style="font-size: 11px;">{{ session('admin_name', 'Admin') }}</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow" aria-labelledby="userMenuMobile">
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route('admin.profile') }}">
|
||||
<i class="fa-solid fa-user-gear me-2"></i> Admin Profile
|
||||
</a>
|
||||
</li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li>
|
||||
<button type="button" onclick="submitAdminLogout()" class="dropdown-item text-danger w-100 text-start border-0 bg-transparent">
|
||||
<i class="fa-solid fa-right-from-bracket me-2"></i> Logout
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@else
|
||||
<a href="{{ route('admin.login') }}" class="btn btn-sm btn-outline-light"><i class="fa-solid fa-right-to-bracket me-1"></i> Sign In</a>
|
||||
@endif
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="sidebar-overlay" id="sidebarOverlay"></div>
|
||||
|
||||
<!-- Sidebar Navigation -->
|
||||
<aside class="sidebar" id="sidebar">
|
||||
<div class="brand">
|
||||
<i class="fa-solid fa-car-side me-2"></i> AutoEdu
|
||||
<span class="admin-badge">Admin</span>
|
||||
</div>
|
||||
|
||||
<nav class="nav">
|
||||
<a href="/admin/dashboard" class="nav-link {{ request()->is('admin/dashboard*') ? 'active' : '' }}">
|
||||
<i class="fa-solid fa-chart-line"></i> Admin Dashboard
|
||||
</a>
|
||||
<a href="{{ route('admin.mycourses') }}" class="nav-link {{ request()->is('admin/adminmycourses*') ? 'active' : '' }}">
|
||||
<i class="fa-solid fa-book-bookmark"></i> Course Management
|
||||
</a>
|
||||
<a href="{{ route('admin.timetable') }}" class="nav-link {{ request()->is('admin/timetable*') ? 'active' : '' }}">
|
||||
<i class="fa-solid fa-calendar-check"></i> Class Timetable
|
||||
</a>
|
||||
<a href="{{ route('admin.results') }}" class="nav-link {{ request()->is('admin/results*') ? 'active' : '' }}">
|
||||
<i class="fa-solid fa-file-invoice-dollar"></i> Exam Results
|
||||
</a>
|
||||
<a href="{{ route('admin.profile') }}" class="nav-link {{ request()->is('admin/profile*') ? 'active' : '' }}">
|
||||
<i class="fa-solid fa-user-gear"></i> Admin Profile
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<div class="sidebar-user-profile">
|
||||
@if(session()->has('admin_id'))
|
||||
<div class="dropdown dropup">
|
||||
<a class="user-dropdown-toggle dropdown-toggle" href="#" role="button" id="userMenuDesktop" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="fa-solid fa-circle-user" style="font-size: 24px; color: var(--theme-yellow);"></i>
|
||||
<span class="text-truncate" style="max-width: 150px;">{{ session('admin_name', 'Admin') }}</span>
|
||||
</a>
|
||||
|
||||
<ul class="dropdown-menu dropdown-menu-start shadow w-100" aria-labelledby="userMenuDesktop">
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route('admin.profile') }}">
|
||||
<i class="fa-solid fa-user-gear me-2"></i> Admin Profile
|
||||
</a>
|
||||
</li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li>
|
||||
<button type="button" onclick="submitAdminLogout()" class="dropdown-item text-danger border-0 bg-transparent w-100 text-start">
|
||||
<i class="fa-solid fa-right-from-bracket me-2"></i> Logout
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@else
|
||||
<div class="d-flex gap-2">
|
||||
<a href="{{ route('admin.login') }}" class="btn btn-outline-light btn-sm w-100">Sign In</a>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<main class="main">
|
||||
@yield('content')
|
||||
</main>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<script>
|
||||
// Sidebar Toggle Logic
|
||||
const toggleBtn = document.getElementById('toggleBtn');
|
||||
const sidebar = document.getElementById('sidebar');
|
||||
const overlay = document.getElementById('sidebarOverlay');
|
||||
|
||||
if(toggleBtn) {
|
||||
toggleBtn.addEventListener('click', () => {
|
||||
sidebar.classList.toggle('show');
|
||||
overlay.classList.toggle('show');
|
||||
});
|
||||
}
|
||||
|
||||
if(overlay) {
|
||||
overlay.addEventListener('click', () => {
|
||||
sidebar.classList.remove('show');
|
||||
overlay.classList.remove('show');
|
||||
});
|
||||
}
|
||||
|
||||
// Admin Logout Logic
|
||||
function submitAdminLogout() {
|
||||
const tokenEl = document.querySelector('meta[name="csrf-token"]');
|
||||
|
||||
fetch('/admin/logout', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'X-CSRF-TOKEN': tokenEl ? tokenEl.getAttribute('content') : ''
|
||||
}
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
window.location.href = '/adminlogin';
|
||||
} else {
|
||||
alert('Logout failed. Please try again.');
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Error:', err);
|
||||
alert('Server side error occurred during logout.');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -4,92 +4,220 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<title>@yield('title', 'Automobile Academic')</title>
|
||||
<title>@yield('title', 'Home') | AutoEdu - Automobile Engineering Academy</title>
|
||||
|
||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='14' fill='%232D355B'/%3E%3Cpath d='M18 28 L24 16 L40 16 L46 28 Z' fill='%23FFEA85'/%3E%3Crect x='8' y='28' width='48' height='14' rx='6' fill='%23FFEA85'/%3E%3Ccircle cx='20' cy='44' r='6' fill='%231F2541' stroke='%23FFEA85' stroke-width='2'/%3E%3Ccircle cx='44' cy='44' r='6' fill='%231F2541' stroke='%23FFEA85' stroke-width='2'/%3E%3C/svg%3E">
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@600;700;800&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
background: #f5f7fb;
|
||||
font-family: 'Inter', 'Segoe UI', sans-serif;
|
||||
background: #F6F6F6;
|
||||
padding-top: 83px;
|
||||
}
|
||||
|
||||
padding-top: 56px;
|
||||
h1, h2, h3, h4, h5, h6,
|
||||
.navbar-brand, .site-footer h4 {
|
||||
font-family: 'Poppins', 'Segoe UI', sans-serif;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background: #5E244E;
|
||||
background:#2D355B;
|
||||
/* background: #3E51B8; */
|
||||
z-index: 1000;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
box-shadow: 0 4px 24px rgba(0,0,0,0.16);
|
||||
border-bottom: 1px solid rgba(255,255,255,0.06);
|
||||
height: 83px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.navbar .container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 24px;
|
||||
font-size: 22px;
|
||||
letter-spacing: -0.01em;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.navbar-brand i {
|
||||
color: #FFEA85;
|
||||
background: rgba(255, 234, 133, 0.12);
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 12px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 18px;
|
||||
transition: transform 0.25s ease;
|
||||
}
|
||||
|
||||
.navbar-brand:hover i {
|
||||
transform: rotate(-8deg) scale(1.05);
|
||||
}
|
||||
|
||||
.navbar-brand:hover {
|
||||
color: #ffc107;
|
||||
color: #f4f4f8;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.navbar-toggler {
|
||||
border: none;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.navbar-nav {
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
color: rgba(255, 255, 255, 0.85) !important;
|
||||
margin-left: 20px;
|
||||
transition: 0.2s ease;
|
||||
font-weight:bold;
|
||||
|
||||
margin-left: 2px;
|
||||
padding: 9px 16px !important;
|
||||
border-radius: 999px;
|
||||
transition: color 0.2s ease, background-color 0.2s ease;
|
||||
font-weight: 600;
|
||||
font-size: 15.5px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-link:hover,
|
||||
.nav-link.active-page {
|
||||
color: #ffc107 !important;
|
||||
font-weight:bold;
|
||||
color: #FFEA85 !important;
|
||||
background: rgba(255, 255, 255, 0.07);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.navbar .btn-outline-light,
|
||||
.navbar .btn-theme-register {
|
||||
border-radius: 999px;
|
||||
font-weight: 600;
|
||||
padding: 8px 22px !important;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.navbar .btn-outline-light:hover,
|
||||
.navbar .btn-theme-register:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.navbar .btn-theme-register {
|
||||
box-shadow: 0 8px 20px rgba(130, 36, 36, 0.35);
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
background: #2F1027;
|
||||
color: #f1e9ee;
|
||||
padding: 60px 0 30px;
|
||||
background:#1F2541;
|
||||
/* background: #182EA4; */
|
||||
color: #ffffff;
|
||||
padding: 64px 0 30px;
|
||||
border-top: 3px solid #FFEA85;
|
||||
}
|
||||
|
||||
.site-footer h4 {
|
||||
color: #fff;
|
||||
color: #FFEA85;
|
||||
font-weight: 700;
|
||||
margin-bottom: 18px;
|
||||
margin-bottom: 20px;
|
||||
letter-spacing: 0.02em;
|
||||
font-size: 16px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.site-footer p {
|
||||
color: #d8c7d3;
|
||||
line-height: 1.6;
|
||||
color: #f1f3f9;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.footer-social {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-top: 22px;
|
||||
}
|
||||
|
||||
.footer-social a {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 234, 133, 0.1);
|
||||
color: #FFEA85;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 14px;
|
||||
transition: transform 0.2s ease, background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.footer-social a:hover {
|
||||
background: #FFEA85;
|
||||
color: #1F2541;
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
|
||||
.user-dropdown-toggle {
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
user-select: none;
|
||||
text-decoration: none !important;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.user-dropdown-toggle:hover {
|
||||
color: #ffc107;
|
||||
color: #FFEA85;
|
||||
}
|
||||
|
||||
.user-profile-name {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
max-width: 120px;
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
font-size: 11px;
|
||||
max-width: 110px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
padding: 8px;
|
||||
margin-top: 12px !important;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
border-radius: 8px;
|
||||
padding: 8px 12px;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.15s ease;
|
||||
}
|
||||
|
||||
.dropdown-item:hover {
|
||||
background-color: #F4F5FA;
|
||||
}
|
||||
|
||||
.footer-links li {
|
||||
|
|
@ -97,48 +225,68 @@
|
|||
}
|
||||
|
||||
.footer-links a {
|
||||
color: #d8c7d3;
|
||||
color: #f1f3f9;
|
||||
text-decoration: none;
|
||||
transition: .2s;
|
||||
}
|
||||
|
||||
.footer-links a:hover {
|
||||
color: #FFC107;
|
||||
color: #FFEA85;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.footer-contact li {
|
||||
margin-bottom: 14px;
|
||||
color: #d8c7d3;
|
||||
color: #f1f3f9;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.footer-contact i {
|
||||
color: #FFC107;
|
||||
margin-top: 3px;
|
||||
color: #FFEA85;
|
||||
background: rgba(255, 234, 133, 0.12);
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border-radius: 50%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.footer-contact a {
|
||||
color: #d8c7d3;
|
||||
color: #f1f3f9;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer-contact a:hover {
|
||||
color: #FFC107;
|
||||
color: #FFEA85;
|
||||
}
|
||||
|
||||
.site-footer hr {
|
||||
border-color: rgba(255,255,255,.15);
|
||||
border-color: rgba(255,255,255,.2);
|
||||
margin: 40px 0 20px;
|
||||
}
|
||||
|
||||
.footer-bottom {
|
||||
color: #b8a6b3;
|
||||
color: #e2e5f3;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Custom Theme Overrides for Buttons */
|
||||
.btn-theme-register {
|
||||
background-color: #F73F52;
|
||||
color: white;
|
||||
border: none;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.btn-theme-register:hover {
|
||||
background-color: #df2c3e;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.animate {
|
||||
animation-duration: 0.2s;
|
||||
animation-fill-mode: both;
|
||||
|
|
@ -184,7 +332,7 @@
|
|||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse" id="menu" style="padding-left:214px;">
|
||||
<div class="collapse navbar-collapse" id="menu">
|
||||
<ul class="navbar-nav ms-auto mb-2 mb-lg-0 align-items-lg-center">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {{ request()->is('/') ? 'active-page' : '' }}" href="/">Home</a>
|
||||
|
|
@ -207,7 +355,7 @@
|
|||
@php
|
||||
$displayName = Auth::user()->first_name . ' ' . Auth::user()->last_name;
|
||||
@endphp
|
||||
<div class="dropdown" style="padding-left:325px;">
|
||||
<div class="dropdown">
|
||||
<a class="user-dropdown-toggle text-white"
|
||||
href="#"
|
||||
role="button"
|
||||
|
|
@ -234,9 +382,10 @@
|
|||
</ul>
|
||||
</div>
|
||||
@else
|
||||
<div class="d-flex gap-2" style="padding-left:214px;">
|
||||
<div class="d-flex gap-2">
|
||||
<a href="/signin" class="btn btn-outline-light btn-sm px-3">Sign In</a>
|
||||
<a href="/signup" class="btn btn-warning btn-sm px-3">Register</a>
|
||||
<!-- Swapped btn-warning for our new custom primary brand color button -->
|
||||
<a href="/signup" class="btn btn-theme-register btn-sm px-3" style="background: #822424;border: 2px solid #FFF;">Register</a>
|
||||
</div>
|
||||
@endif
|
||||
</li>
|
||||
|
|
@ -245,8 +394,6 @@
|
|||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
|
||||
<main>
|
||||
@yield('content')
|
||||
</main>
|
||||
|
|
@ -257,6 +404,12 @@
|
|||
<div class="col-md-4">
|
||||
<h4>Automobile Academic</h4>
|
||||
<p>Providing excellence in Automotive Engineering Education, Innovation and Research.</p>
|
||||
<div class="footer-social">
|
||||
<a href="#" aria-label="Facebook"><i class="fa-brands fa-facebook-f"></i></a>
|
||||
<a href="#" aria-label="Instagram"><i class="fa-brands fa-instagram"></i></a>
|
||||
<a href="#" aria-label="LinkedIn"><i class="fa-brands fa-linkedin-in"></i></a>
|
||||
<a href="#" aria-label="YouTube"><i class="fa-brands fa-youtube"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
|
|
|
|||
|
|
@ -4,77 +4,98 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<title>Responsive Student Portal</title>
|
||||
<title>@yield('title', 'Student Portal - Automobile Academic')</title>
|
||||
|
||||
<!-- Font Awesome Icons -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<!-- Google Fonts & Font Awesome Icons & Bootstrap 5 -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
/* Global Root Variables */
|
||||
:root {
|
||||
--primary: #000000;
|
||||
--background: #f5f6fb;
|
||||
--theme-navy: #1E233E;
|
||||
--theme-footer-navy: #15182C;
|
||||
--theme-red: #822424;
|
||||
--theme-red-hover: #df2c3e;
|
||||
--theme-yellow: #FFEA85;
|
||||
--theme-bg: #F4F6F9;
|
||||
--sidebar-width: 260px;
|
||||
--text-color: #333333;
|
||||
--sidebar-bg: #5E244E;
|
||||
--text-dark: #1E293B;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--background);
|
||||
color: var(--text-color);
|
||||
background-color: var(--theme-bg);
|
||||
color: var(--text-dark);
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* ---------- Sidebar Style ---------- */
|
||||
.sidebar {
|
||||
width: var(--sidebar-width);
|
||||
height: 100vh;
|
||||
background: var(--sidebar-bg);
|
||||
background: linear-gradient(180deg, #1E233E 0%, #15182C 100%);
|
||||
color: #fff;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 24px 0;
|
||||
transition: all 0.3s ease;
|
||||
transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
z-index: 1030;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 4px 0 20px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.sidebar .brand {
|
||||
padding: 0 24px 24px;
|
||||
font-weight: 700;
|
||||
padding: 0 20px 22px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
border-bottom: 1px solid rgba(255,255,255,.08);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.brand-logo-icon {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 12px;
|
||||
background: linear-gradient(135deg, var(--theme-red) 0%, var(--theme-red-hover) 100%);
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.2rem;
|
||||
border-bottom: 1px solid rgba(255,255,255,.12);
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-shadow: 0 6px 16px rgba(130, 36, 36, 0.35);
|
||||
}
|
||||
|
||||
/* User Profile Section inside Sidebar */
|
||||
.sidebar-user-profile {
|
||||
padding: 15px 24px;
|
||||
border-bottom: 1px solid rgba(255,255,255,.12);
|
||||
margin-bottom: 15px;
|
||||
.brand-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.sidebar-user-profile .dropdown-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-size: 0.95rem;
|
||||
.brand-text span {
|
||||
font-weight: 800;
|
||||
font-size: 1.25rem;
|
||||
color: #ffffff;
|
||||
letter-spacing: -0.5px;
|
||||
}
|
||||
|
||||
.brand-sub {
|
||||
font-size: 0.65rem;
|
||||
font-weight: 700;
|
||||
color: var(--theme-yellow);
|
||||
letter-spacing: 1.5px;
|
||||
opacity: 0.85;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.sidebar .nav {
|
||||
|
|
@ -82,63 +103,204 @@
|
|||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
padding: 0 14px;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.sidebar .nav-link {
|
||||
color: rgba(255,255,255,.75);
|
||||
padding: 14px 24px;
|
||||
font-size: .95rem;
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
padding: 13px 18px;
|
||||
font-size: 0.93rem;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
transition: .2s;
|
||||
border-left: 3px solid transparent;
|
||||
gap: 14px;
|
||||
transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
border-radius: 14px;
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sidebar .nav-link i {
|
||||
width: 20px;
|
||||
width: 22px;
|
||||
text-align: center;
|
||||
font-size: 1.1rem;
|
||||
transition: transform 0.25s ease, color 0.25s ease;
|
||||
}
|
||||
|
||||
.sidebar .nav-link:hover {
|
||||
background: rgba(255,255,255,.06);
|
||||
color: #fff;
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
color: var(--theme-yellow) !important;
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.sidebar .nav-link:hover i {
|
||||
transform: scale(1.15);
|
||||
color: var(--theme-yellow);
|
||||
}
|
||||
|
||||
.sidebar .nav-link.active {
|
||||
background: rgba(255,255,255,.1);
|
||||
color: #fff;
|
||||
border-left: 3px solid #fff;
|
||||
font-weight: 600;
|
||||
background: linear-gradient(90deg, rgba(255, 234, 133, 0.16) 0%, rgba(255, 234, 133, 0.06) 100%);
|
||||
color: var(--theme-yellow) !important;
|
||||
font-weight: 700;
|
||||
border-left: 4px solid var(--theme-yellow);
|
||||
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.15);
|
||||
border-radius: 4px 14px 14px 4px;
|
||||
}
|
||||
|
||||
.sidebar .logout-link {
|
||||
color: rgba(255,255,255,.6);
|
||||
.sidebar .nav-link.active i {
|
||||
color: var(--theme-yellow);
|
||||
}
|
||||
|
||||
.sidebar-user-profile {
|
||||
padding: 16px 18px;
|
||||
border-top: 1px solid rgba(255,255,255,.08);
|
||||
margin-top: auto;
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.sidebar .logout-link:hover {
|
||||
.sidebar-user-profile .user-dropdown-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
color: #fff;
|
||||
background: rgba(220,53,69,.25);
|
||||
text-decoration: none;
|
||||
transition: all 0.2s ease;
|
||||
padding: 8px 10px;
|
||||
border-radius: 12px;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.sidebar-user-profile .user-dropdown-toggle:hover {
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
border-color: rgba(255, 234, 133, 0.3);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.user-avatar-badge-sm {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, var(--theme-navy) 0%, var(--theme-footer-navy) 100%);
|
||||
border: 2px solid var(--theme-yellow);
|
||||
color: var(--theme-yellow);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 800;
|
||||
font-size: 0.95rem;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 4px 10px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.user-info-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.user-name-text {
|
||||
font-weight: 700;
|
||||
font-size: 0.88rem;
|
||||
color: #ffffff;
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.user-email-text {
|
||||
font-size: 0.72rem;
|
||||
font-style: italic;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* Dark Glassmorphic User Dropdown Popup */
|
||||
.user-dropdown-menu {
|
||||
background: linear-gradient(145deg, #1A1E36 0%, #111428 100%) !important;
|
||||
border: 1px solid rgba(255, 255, 255, 0.12) !important;
|
||||
box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5) !important;
|
||||
border-radius: 16px !important;
|
||||
margin-bottom: 12px !important;
|
||||
padding: 8px !important;
|
||||
width: 220px;
|
||||
backdrop-filter: blur(16px);
|
||||
}
|
||||
|
||||
.user-dropdown-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
color: #ffffff !important;
|
||||
text-decoration: none;
|
||||
padding: 10px 12px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.user-dropdown-item:hover {
|
||||
background: rgba(255, 255, 255, 0.08) !important;
|
||||
transform: translateX(3px);
|
||||
}
|
||||
|
||||
.dropdown-item-icon-blue {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 10px;
|
||||
background: rgba(59, 130, 246, 0.15);
|
||||
color: #60A5FA;
|
||||
border: 1px solid rgba(59, 130, 246, 0.3);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.95rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.dropdown-item-icon-red {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 10px;
|
||||
background: rgba(239, 68, 68, 0.15);
|
||||
color: #F87171;
|
||||
border: 1px solid rgba(239, 68, 68, 0.3);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.95rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* ---------- Main Content Layout ---------- */
|
||||
.main {
|
||||
margin-left: var(--sidebar-width);
|
||||
width: calc(100% - var(--sidebar-width));
|
||||
min-height: 100vh;
|
||||
padding: 40px;
|
||||
background: var(--background);
|
||||
padding: 32px 40px;
|
||||
background: var(--theme-bg);
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.portal-content-container {
|
||||
width: 100%;
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Mobile Header Toggle Bar */
|
||||
.mobile-header {
|
||||
display: none;
|
||||
background: #fff;
|
||||
padding: 15px 20px;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.05);
|
||||
background: var(--theme-navy);
|
||||
color: #ffffff;
|
||||
padding: 12px 20px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: fixed;
|
||||
|
|
@ -151,21 +313,24 @@
|
|||
.sidebar-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.5rem;
|
||||
font-size: 1.4rem;
|
||||
cursor: pointer;
|
||||
color: var(--sidebar-bg);
|
||||
color: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sidebar-toggle:hover {
|
||||
color: var(--theme-yellow);
|
||||
}
|
||||
|
||||
.mobile-brand {
|
||||
font-weight: 700;
|
||||
font-size: 1.1rem;
|
||||
color: #333;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Overlay Background when sidebar open on Mobile */
|
||||
.sidebar-overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
|
|
@ -173,7 +338,7 @@
|
|||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0,0,0,0.4);
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 1025;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
|
|
@ -184,7 +349,6 @@
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
/* ---------- Responsive Media Queries (Mobile & Tablets) ---------- */
|
||||
@media (max-width: 991px) {
|
||||
.sidebar {
|
||||
left: calc(-1 * var(--sidebar-width));
|
||||
|
|
@ -196,7 +360,7 @@
|
|||
|
||||
.main {
|
||||
margin-left: 0;
|
||||
padding: 90px 20px 20px 20px;
|
||||
padding: 85px 20px 20px 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
|
@ -213,22 +377,23 @@
|
|||
<button class="sidebar-toggle" id="toggleBtn" aria-label="Toggle Sidebar">
|
||||
<i class="fa-solid fa-bars"></i>
|
||||
</button>
|
||||
<div class="mobile-brand">Student Portal</div>
|
||||
<div class="mobile-brand">
|
||||
<i class="fa-solid fa-car-side me-1"></i> AutoEdu Portal
|
||||
</div>
|
||||
|
||||
<!-- Mobile View User Profile Header Dropdown -->
|
||||
<div class="mobile-user-profile">
|
||||
@if(Auth::check())
|
||||
@if(session()->has('student_id'))
|
||||
<div class="dropdown">
|
||||
<a class="text-dark no-toggle-icon" href="#" role="button" id="userMenuMobile" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="fa-solid fa-circle-user" style="font-size: 35px; color: var(--sidebar-bg);"></i>
|
||||
<strong>{{ Auth::user()->first_name }}</strong>
|
||||
<a class="text-white text-decoration-none dropdown-toggle d-flex flex-column align-items-center justify-content-center gap-0" href="#" role="button" id="userMenuMobile" data-bs-toggle="dropdown" aria-expanded="false" style="line-height: 1.1;">
|
||||
<i class="fa-solid fa-circle-user" style="font-size: 24px; color: var(--theme-yellow);"></i>
|
||||
<span class="fst-italic" style="font-size: 11px;">{{ session('student_name') }}</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow" aria-labelledby="userMenuMobile">
|
||||
<li class="px-3 py-2 ">
|
||||
<!-- <small class="text-muted">Signed in as</small><br> -->
|
||||
<!-- <strong>{{ Auth::user()->first_name }}</strong> -->
|
||||
<li>
|
||||
<a class="dropdown-item" href="{{ route('StudentProfile') }}">
|
||||
<i class="fa-solid fa-user me-2"></i> Profile
|
||||
</a>
|
||||
</li>
|
||||
<li><a class="dropdown-item mt-1" href="/StudentProfile"><i class="fa-solid fa-user me-2"></i> Profile</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li>
|
||||
<button type="button" onclick="submitLogout()" class="dropdown-item text-danger w-100 text-start border-0 bg-transparent">
|
||||
|
|
@ -238,142 +403,166 @@
|
|||
</ul>
|
||||
</div>
|
||||
@else
|
||||
<a href="/signin" class="btn btn-sm btn-outline-dark"><i class="fa-solid fa-right-to-bracket"></i></a>
|
||||
<a href="/" class="btn btn-sm btn-outline-light"><i class="fa-solid fa-right-to-bracket me-1"></i> Sign In</a>
|
||||
@endif
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Overlay dim background element -->
|
||||
<div class="sidebar-overlay" id="sidebarOverlay"></div>
|
||||
|
||||
<!-- Sidebar Navigation -->
|
||||
<aside class="sidebar" id="sidebar">
|
||||
<div class="brand">
|
||||
<i class="fa-solid fa-graduation-cap"></i> Student Portal
|
||||
<div class="brand-logo-icon">
|
||||
<i class="fa-solid fa-car-side"></i>
|
||||
</div>
|
||||
<div class="brand-text">
|
||||
<span>AutoEdu</span>
|
||||
<small class="brand-sub">STUDENT ACADEMY</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar Active User Profile Details (Desktop View) -->
|
||||
|
||||
|
||||
<nav class="nav">
|
||||
<a href="/Dashboard" class="nav-link ">
|
||||
<a href="/student-portal" class="nav-link {{ request()->is('Dashboard*') || request()->is('student-portal*') ? 'active' : '' }}">
|
||||
<i class="fa-solid fa-gauge"></i> Dashboard
|
||||
</a>
|
||||
<a href="/mycourse" class="nav-link">
|
||||
<a href="/mycourse" class="nav-link {{ request()->is('mycourse*') ? 'active' : '' }}">
|
||||
<i class="fa-solid fa-book"></i> My Courses
|
||||
</a>
|
||||
<a href="/timetable" class="nav-link">
|
||||
<a href="/timetable" class="nav-link {{ request()->is('timetable*') ? 'active' : '' }}">
|
||||
<i class="fa-solid fa-calendar-days"></i> Class Timetable
|
||||
</a>
|
||||
<!-- <a href="/Assignments" class="nav-link">
|
||||
<i class="fa-solid fa-file-lines"></i>Assignments
|
||||
</a> -->
|
||||
<a href="/results" class="nav-link">
|
||||
<a href="/results" class="nav-link {{ request()->is('results*') ? 'active' : '' }}">
|
||||
<i class="fa-solid fa-square-poll-vertical"></i> Exam Results
|
||||
</a>
|
||||
|
||||
<a href="/Studentguidelines" class="nav-link">
|
||||
<a href="/Studentguidelines" class="nav-link {{ request()->is('Studentguidelines*') ? 'active' : '' }}">
|
||||
<i class="fa-solid fa-book-open"></i> Student Guidelines
|
||||
</a>
|
||||
<a href="/Feedback&Complain" class="nav-link">
|
||||
<a href="/Feedback&Complain" class="nav-link {{ request()->is('Feedback&Complain*') ? 'active' : '' }}">
|
||||
<i class="fa-solid fa-comments"></i> Feedback & Complain
|
||||
</a>
|
||||
<a href="/StudentProfile" class="nav-link">
|
||||
<a href="{{ route('StudentProfile') }}" class="nav-link {{ request()->routeIs('StudentProfile') ? 'active' : '' }}">
|
||||
<i class="fa-solid fa-user"></i> Student Profile
|
||||
</a>
|
||||
|
||||
|
||||
</nav>
|
||||
|
||||
<div class="sidebar-user-profile">
|
||||
@if(Auth::check())
|
||||
@php
|
||||
$displayName = Auth::user()->first_name . ' ' . Auth::user()->last_name;
|
||||
@endphp
|
||||
<div class="dropdown">
|
||||
<a class="dropdown-toggle" href="#" role="button" id="userMenuDesktop" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="fa-solid fa-circle-user" style="font-size: 24px;"></i>
|
||||
<span class="user-profile-name text-truncate" style="max-width: 160px;">{{ $displayName }}</span>
|
||||
@if(session()->has('student_id'))
|
||||
<div class="dropdown dropup">
|
||||
<a class="user-dropdown-toggle dropdown-toggle" href="#" role="button" id="userMenuDesktop" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<div class="user-avatar-badge-sm">
|
||||
{{ strtoupper(substr(session('student_name', 'S'), 0, 1)) }}
|
||||
</div>
|
||||
<div class="user-info-text">
|
||||
<span class="user-name-text">{{ session('student_name', 'Student') }}</span>
|
||||
<span class="user-email-text">Active Session</span>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<ul class="dropdown-menu dropdown-menu-start shadow w-100" aria-labelledby="userMenuDesktop">
|
||||
<ul class="dropdown-menu user-dropdown-menu shadow-lg p-2 animate slideIn" aria-labelledby="userMenuDesktop">
|
||||
<li>
|
||||
<a class="dropdown-item" href="/StudentProfile">
|
||||
<i class="fa-solid fa-user me-2"></i> Profile
|
||||
<a class="dropdown-item user-dropdown-item py-2.5 px-3 rounded-3" href="{{ route('StudentProfile') }}">
|
||||
<div class="dropdown-item-icon-blue">
|
||||
<i class="fa-solid fa-user-gear"></i>
|
||||
</div>
|
||||
<div>
|
||||
<span class="fw-bold d-block text-white" style="font-size: 0.88rem;">My Profile</span>
|
||||
<small class="text-white-50" style="font-size: 0.72rem;">View & edit details</small>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><hr class="dropdown-divider border-white opacity-10 my-1"></li>
|
||||
<li>
|
||||
<a href="#" onclick="submitLogout(); return false;" class="nav-link logout-link mt-auto" style="color:black;">
|
||||
<i class="fa-solid fa-right-from-bracket"></i>Logout
|
||||
</a>
|
||||
<button type="button" onclick="submitLogout()" class="dropdown-item user-dropdown-item py-2.5 px-3 rounded-3 border-0 bg-transparent w-100 text-start">
|
||||
<div class="dropdown-item-icon-red">
|
||||
<i class="fa-solid fa-right-from-bracket"></i>
|
||||
</div>
|
||||
<div>
|
||||
<span class="fw-bold d-block text-danger" style="font-size: 0.88rem;">Logout</span>
|
||||
<small class="text-danger-subtle opacity-75" style="font-size: 0.72rem;">Sign out of session</small>
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@else
|
||||
<div class="d-flex gap-2 px-2">
|
||||
<a href="/signin" class="btn btn-outline-light btn-sm w-50">Sign In</a>
|
||||
<a href="/signup" class="btn btn-warning btn-sm w-50">Register</a>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="/" class="btn btn-outline-light btn-sm w-100 rounded-pill">Sign In</a>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
|
||||
<!-- Main Content Area -->
|
||||
<main class="main">
|
||||
@yield('content')
|
||||
</main>
|
||||
|
||||
<!-- Sidebar Toggle JavaScript -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<script>
|
||||
// Sidebar Toggle Logic
|
||||
const toggleBtn = document.getElementById('toggleBtn');
|
||||
const sidebar = document.getElementById('sidebar');
|
||||
const overlay = document.getElementById('sidebarOverlay');
|
||||
|
||||
// Function to toggle sidebar view
|
||||
if(toggleBtn) {
|
||||
toggleBtn.addEventListener('click', () => {
|
||||
sidebar.classList.toggle('show');
|
||||
overlay.classList.toggle('show');
|
||||
});
|
||||
}
|
||||
|
||||
// Close sidebar if user clicks outside of it
|
||||
if(overlay) {
|
||||
overlay.addEventListener('click', () => {
|
||||
sidebar.classList.remove('show');
|
||||
overlay.classList.remove('show');
|
||||
});
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
}
|
||||
|
||||
<script>
|
||||
// Logout Logic
|
||||
function submitLogout() {
|
||||
const tokenEl = document.querySelector('meta[name="csrf-token"]');
|
||||
const csrfToken = tokenEl ? tokenEl.getAttribute('content') : '';
|
||||
|
||||
if (!csrfToken) {
|
||||
console.error('CSRF token meta tag not found!');
|
||||
alert('Security token missing. Refreshing page...');
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('/studentlogout', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'X-CSRF-TOKEN': tokenEl ? tokenEl.getAttribute('content') : ''
|
||||
'X-CSRF-TOKEN': csrfToken
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
if (!res.ok) {
|
||||
return res.text().then(text => { throw new Error(text) });
|
||||
|
||||
if (res.status === 419) {
|
||||
alert('Session expired. Page will reload.');
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`Server returned status ${res.status}`);
|
||||
}
|
||||
|
||||
return res.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
alert('Logged out successfully!');
|
||||
window.location.href = '/students';
|
||||
if (data && data.success) {
|
||||
window.location.href = '/';
|
||||
} else {
|
||||
alert('Logout failed. Please try again.');
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Error:', err);
|
||||
alert('Server side error occurred during logout.');
|
||||
console.error('Logout Error:', err);
|
||||
alert('An error occurred during logout.');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Password Reset OTP - Academy</title>
|
||||
<style>
|
||||
body, table, td, a { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
|
||||
table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
|
||||
img { -ms-interpolation-mode: bicubic; border: 0; height: auto; line-height: 100%; outline: none; text-decoration: none; }
|
||||
body { height: 100% !important; margin: 0 !important; padding: 0 !important; width: 100% !important; background-color: #f4f7f6; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
|
||||
</style>
|
||||
</head>
|
||||
<body style="margin: 0; padding: 0; background-color: #f4f7f6;">
|
||||
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td align="center" style="padding: 40px 10px;">
|
||||
<!-- Main Container -->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 550px; background-color: #ffffff; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 15px rgba(0,0,0,0.05);">
|
||||
|
||||
<!-- Header / Logo Area -->
|
||||
<tr>
|
||||
<td align="center" style="padding: 30px 20px; background-color: #1a2b4c;">
|
||||
<!-- Academy Logo / Branding -->
|
||||
<h2 style="color: #ffffff; margin: 0; font-size: 24px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase;">
|
||||
ACADEMY
|
||||
</h2>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Body Content -->
|
||||
<tr>
|
||||
<td style="padding: 40px 30px; text-align: center;">
|
||||
<h1 style="color: #20396b; font-size: 22px; font-weight: 700; margin-top: 0; margin-bottom: 12px;">
|
||||
Reset Your Password
|
||||
</h1>
|
||||
|
||||
<p style="color: #683636; font-size: 15px; line-height: 22px; margin-bottom: 25px;">
|
||||
Hello,<br>
|
||||
We received a request to reset the password for your Academy account. Use the Verification Code (OTP) below to proceed.
|
||||
</p>
|
||||
|
||||
<!-- OTP Box -->
|
||||
<div style="background-color: #f0f4f9; border: 2px dashed #0236b9; border-radius: 8px; padding: 18px; margin: 20px 0; display: inline-block; width: 80%;">
|
||||
<span style="font-size: 32px; font-weight: 800; color: #0236b9; letter-spacing: 6px; font-family: 'Courier New', Courier, monospace;">
|
||||
{{ $otp }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<p style="color: #888888; font-size: 13px; line-height: 18px; margin-top: 25px;">
|
||||
This OTP is valid for <strong>10 minutes</strong>. If you did not request a password reset, please ignore this email.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Divider -->
|
||||
<tr>
|
||||
<td style="padding: 0 30px;">
|
||||
<hr style="border: none; border-top: 1px solid #eeeeee; margin: 0;">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Footer -->
|
||||
<tr>
|
||||
<td style="padding: 25px 30px; text-align: center; background-color: #fafafa;">
|
||||
<p style="color: #999999; font-size: 12px; margin: 0 0 8px 0;">
|
||||
Regards,<br>
|
||||
<strong>Academy Learning Team</strong>
|
||||
</p>
|
||||
<p style="color: #cccccc; font-size: 11px; margin: 0;">
|
||||
© {{ date('Y') }} Academy. All rights reserved.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Welcome to Student Registration</title>
|
||||
</head>
|
||||
<body style="margin: 0; padding: 0; background-color: #f5f7fb; font-family: 'Segoe UI', Arial, sans-serif; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%;">
|
||||
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="background-color: #f5f7fb; padding: 40px 10px;">
|
||||
<tr>
|
||||
<td align="center">
|
||||
|
||||
<!-- Main Email Card -->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="max-width: 520px; background-color: #ffffff; border-radius: 18px; overflow: hidden; box-shadow: 0 15px 40px rgba(0,0,0,0.12);">
|
||||
|
||||
<!-- Header Banner -->
|
||||
<tr>
|
||||
<td align="center" style="background-color: #5E244E; padding: 35px 20px;">
|
||||
<h1 style="color: #ffffff; margin: 0; font-size: 26px; font-weight: 700; letter-spacing: 0.5px;">
|
||||
Student Registration
|
||||
</h1>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Body Content -->
|
||||
<tr>
|
||||
<td style="padding: 40px 35px; color: #334155; font-size: 15px; line-height: 1.6;">
|
||||
|
||||
<h2 style="color: #222222; margin-top: 0; margin-bottom: 15px; font-size: 22px; font-weight: 700;">
|
||||
Welcome, {{ $user->first_name }}! 👋
|
||||
</h2>
|
||||
|
||||
<p style="margin-bottom: 25px; color: #555555; font-size: 15px;">
|
||||
Thank you for signing up. Your account has been created successfully! Here are your account details:
|
||||
</p>
|
||||
|
||||
<!-- Account Details Box -->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="background-color: #f8f9fa; border-radius: 12px; padding: 20px; margin-bottom: 30px; border: 1px solid #e2e8f0;">
|
||||
<tr>
|
||||
<td>
|
||||
<p style="margin: 0 0 8px 0; font-size: 14px; color: #744a68;">
|
||||
<strong>Full Name:</strong> {{ $user->first_name }} {{ $user->last_name }}
|
||||
</p>
|
||||
<p style="margin: 0 0 8px 0; font-size: 14px; color: #744a68;">
|
||||
<strong>Email Address:</strong> {{ $user->email }}
|
||||
</p>
|
||||
<p style="margin: 0; font-size: 14px; color: #744a68;">
|
||||
<strong>Mobile Number:</strong> {{ $user->phone }}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p style="margin-bottom: 30px; color: #555555; font-size: 15px;">
|
||||
You can now sign in using your email and password to access your student dashboard.
|
||||
</p>
|
||||
|
||||
<!-- Action Button (Matching Page Button Style) -->
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="{{ url('/signin') }}" style="background-color: #822424; color: #ffffff; text-decoration: none; padding: 14px 35px; border-radius: 8px; font-weight: 600; font-size: 16px; display: inline-block; transition: background 0.2s;">
|
||||
Sign In to Your Account
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Footer -->
|
||||
<tr>
|
||||
<td align="center" style="background-color: #f8f9fa; padding: 20px; border-top: 1px solid #edf2f7; font-size: 13px; color: #666666;">
|
||||
<p style="margin: 0 0 5px 0;">If you didn't create this account, please ignore this email.</p>
|
||||
<p style="margin: 0; font-weight: 600; color: #744a68;">© {{ date('Y') }} Student Registration System</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
@extends('layouts.studentportalnav')
|
||||
|
||||
@section('title', 'Module Details')
|
||||
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--theme-navy: #2D355B;
|
||||
--theme-navy-dark: #1F2541;
|
||||
--theme-red: #822424;
|
||||
--theme-red-hover: #df2c3e;
|
||||
--theme-yellow: #FFEA85;
|
||||
--bg-light: #F6F6F6;
|
||||
--white: #ffffff;
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--bg-light);
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
}
|
||||
|
||||
.main-portal-content {
|
||||
padding: 10px 5px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* Header styling */
|
||||
.module-header {
|
||||
background: var(--theme-navy);
|
||||
color: var(--white);
|
||||
border-radius: 16px;
|
||||
padding: 25px 30px;
|
||||
margin-bottom: 25px;
|
||||
border-left: 5px solid var(--theme-red);
|
||||
}
|
||||
|
||||
/* Video Wrapper */
|
||||
.video-container {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%; /* 16:9 Aspect Ratio */
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 14px;
|
||||
background: #000;
|
||||
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.video-container iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* Card Styling */
|
||||
.content-card {
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 14px;
|
||||
background: var(--white);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.03);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* Lesson List */
|
||||
.lesson-list .list-group-item {
|
||||
border: none;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
padding: 14px 20px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.lesson-list .list-group-item:hover {
|
||||
background-color: #f8fafc;
|
||||
}
|
||||
|
||||
.lesson-list .list-group-item.active {
|
||||
background-color: rgba(130, 36, 36, 0.08);
|
||||
color: var(--theme-red);
|
||||
font-weight: 600;
|
||||
border-left: 4px solid var(--theme-red);
|
||||
}
|
||||
|
||||
.btn-theme-red {
|
||||
background-color: var(--theme-red) !important;
|
||||
border-color: var(--theme-red) !important;
|
||||
color: #fff !important;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.btn-theme-red:hover {
|
||||
background-color: var(--theme-red-hover) !important;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.main-portal-content { padding: 15px; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="main-portal-content">
|
||||
<div class="container-fluid">
|
||||
|
||||
<!-- Back Button & Header -->
|
||||
<div class="mb-3">
|
||||
<a href="{{ route('mycourse') }}" class="text-decoration-none text-muted small fw-semibold">
|
||||
<i class="fa fa-arrow-left me-1"></i> Back to My Course
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="module-header d-flex flex-wrap align-items-center justify-content-between gap-3">
|
||||
<div>
|
||||
<span class="badge bg-danger mb-2">Module {{ $moduleId ?? 1 }}</span>
|
||||
<h2 class="fw-bold mb-1">Introduction & Fundamentals</h2>
|
||||
<p class="mb-0 opacity-75 small">Learn the basic concepts, core principles, and foundational theories.</p>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-outline-light btn-sm px-3">
|
||||
<i class="fa-solid fa-check-circle me-1"></i> Mark as Complete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content Area -->
|
||||
<div class="row g-4">
|
||||
|
||||
<!-- LEFT: Video Player & Module Details -->
|
||||
<div class="col-lg-8 col-12">
|
||||
|
||||
<!-- Video Container -->
|
||||
<div class="content-card p-2">
|
||||
<div class="video-container">
|
||||
<!-- Sample Video URL (replace with actual video stream/iframe) -->
|
||||
<iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" title="Lesson Video" allowfullscreen></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Module Description Card -->
|
||||
<div class="content-card p-4">
|
||||
<h4 class="fw-bold mb-3" style="color: var(--theme-navy);">Overview & Description</h4>
|
||||
<p class="text-secondary lh-base">
|
||||
In this module, you will explore the essential foundational topics. We will cover step-by-step concepts to help you build a strong understanding before moving on to the advanced practical modules.
|
||||
</p>
|
||||
|
||||
<hr class="my-4" style="color: #cbd5e1;">
|
||||
|
||||
<h5 class="fw-bold mb-3" style="color: var(--theme-navy);">Resources & Downloads</h5>
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
<a href="#" class="btn btn-light border btn-sm text-dark">
|
||||
<i class="fa-solid fa-file-pdf text-danger me-2"></i> Lecture Notes.pdf
|
||||
</a>
|
||||
<a href="#" class="btn btn-light border btn-sm text-dark">
|
||||
<i class="fa-solid fa-file-lines text-primary me-2"></i> Assignment Guide.docx
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation Buttons -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<button class="btn btn-secondary btn-sm px-4 py-2" disabled>
|
||||
<i class="fa fa-chevron-left me-1"></i> Previous Module
|
||||
</button>
|
||||
<a href="#" class="btn btn-theme-red btn-sm px-4 py-2">
|
||||
Next Module <i class="fa fa-chevron-right ms-1"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- RIGHT: Lesson Playlist Sidebar -->
|
||||
<div class="col-lg-4 col-12">
|
||||
<div class="content-card overflow-hidden">
|
||||
<div class="p-3 border-bottom bg-light">
|
||||
<h6 class="fw-bold mb-0" style="color: var(--theme-navy);">
|
||||
<i class="fa-solid fa-list-ul me-2" style="color: var(--theme-red);"></i> Course Playlist
|
||||
</h6>
|
||||
</div>
|
||||
|
||||
<ul class="list-group list-group-flush lesson-list">
|
||||
<li class="list-group-item active d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<i class="fa-solid fa-circle-play me-2"></i>
|
||||
<span>1. Introduction to Course</span>
|
||||
</div>
|
||||
<span class="badge bg-danger rounded-pill">10 mins</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<i class="fa-regular fa-circle-play me-2 text-muted"></i>
|
||||
<span>2. Core Concepts Explained</span>
|
||||
</div>
|
||||
<span class="badge bg-secondary rounded-pill">15 mins</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<i class="fa-regular fa-circle-play me-2 text-muted"></i>
|
||||
<span>3. Practical Application</span>
|
||||
</div>
|
||||
<span class="badge bg-secondary rounded-pill">20 mins</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<i class="fa-solid fa-lock me-2 text-muted"></i>
|
||||
<span class="text-muted">4. Summary & Quiz</span>
|
||||
</div>
|
||||
<span class="badge bg-light text-dark border">Locked</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
|
@ -1,371 +1,106 @@
|
|||
@extends('layouts.studentportalnav')
|
||||
|
||||
@section('title', 'My Course')
|
||||
@section('title', 'My Courses & Modules')
|
||||
|
||||
@section('content')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--purple-main: #5E244E;
|
||||
--purple-dark: #4a1c3e;
|
||||
--purple-light: #744a68;
|
||||
--gold-accent: #D4AF37;
|
||||
--gold-hover: #b8972e;
|
||||
--bg-light: #f8fafc;
|
||||
--theme-navy: #2D355B;
|
||||
--theme-red: #822424;
|
||||
--bg-light: #F6F6F6;
|
||||
--white: #ffffff;
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--bg-light);
|
||||
font-family: 'Poppins', sans-serif;
|
||||
}
|
||||
|
||||
.main-portal-content {
|
||||
padding: 20px 15px;
|
||||
min-height: 100vh;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
/* Premium Hero Section */
|
||||
.hero {
|
||||
background: linear-gradient(135deg, var(--purple-main) 0%, var(--purple-dark) 100%) !important;
|
||||
color: var(--white) !important;
|
||||
border-radius: 20px;
|
||||
padding: 30px 20px;
|
||||
margin-bottom: 30px;
|
||||
box-shadow: 0 10px 30px rgba(74, 28, 62, 0.15);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -30%;
|
||||
right: -10%;
|
||||
width: 350px;
|
||||
height: 350px;
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Course Card */
|
||||
.course-card {
|
||||
border: none !important;
|
||||
border-radius: 20px !important;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05) !important;
|
||||
background: var(--white);
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.course-card img {
|
||||
height: 200px;
|
||||
object-fit: cover;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Sidebar Info Boxes */
|
||||
.info-box {
|
||||
border-radius: 16px !important;
|
||||
padding: 20px 24px;
|
||||
background: var(--white);
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.03) !important;
|
||||
border: 1px solid rgba(94, 36, 78, 0.05) !important;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.info-box:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.06) !important;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
body { background: var(--bg-light); font-family: 'Segoe UI', sans-serif; }
|
||||
.course-header {
|
||||
background: linear-gradient(135deg, #2B293F 0%, #94A6F959 100%);
|
||||
color: var(--white);
|
||||
border-radius: 12px;
|
||||
font-size: 18px;
|
||||
background: rgba(94, 36, 78, 0.08);
|
||||
color: var(--purple-main);
|
||||
padding: 20px;
|
||||
margin-bottom: 15px;
|
||||
border-left: 5px solid var(--theme-red);
|
||||
}
|
||||
|
||||
/* Modules Card */
|
||||
.module-card {
|
||||
border: 1px solid rgba(94, 36, 78, 0.06) !important;
|
||||
border-radius: 16px !important;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
background: var(--white);
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.02) !important;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.module-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 12px 25px rgba(0, 0, 0, 0.08) !important;
|
||||
border-color: var(--purple-light) !important;
|
||||
}
|
||||
|
||||
/* Progress bar customizations */
|
||||
.progress {
|
||||
height: 10px !important;
|
||||
border-radius: 50px !important;
|
||||
background-color: #f1f5f9 !important;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
border-radius: 50px !important;
|
||||
background: linear-gradient(90deg, var(--gold-accent), #f4d05e) !important;
|
||||
}
|
||||
|
||||
/* Status Badges */
|
||||
.status {
|
||||
.semester-badge {
|
||||
background-color: var(--theme-navy);
|
||||
color: #fff;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
padding: 5px 14px;
|
||||
border-radius: 50px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.completed { background: rgba(94, 36, 78, 0.1); color: var(--purple-main); }
|
||||
.progressing { background: rgba(212, 175, 55, 0.15); color: #9c7e1c; }
|
||||
.locked { background: #f1f5f9; color: #64748b; }
|
||||
|
||||
/* Custom Buttons */
|
||||
.btn-gold {
|
||||
background-color: var(--gold-accent) !important;
|
||||
border-color: var(--gold-accent) !important;
|
||||
color: #fff !important;
|
||||
border-radius: 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.btn-gold:hover { background-color: var(--gold-hover) !important; }
|
||||
|
||||
.btn-purple {
|
||||
background-color: var(--purple-main) !important;
|
||||
border-color: var(--purple-main) !important;
|
||||
color: #fff !important;
|
||||
border-radius: 10px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.btn-purple:hover { background-color: var(--purple-dark) !important; }
|
||||
|
||||
.btn-continue {
|
||||
background-color: #fff !important;
|
||||
color: var(--purple-main) !important;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.btn-continue:hover { background-color: #f1f5f9 !important; }
|
||||
|
||||
/* Responsive Media Queries */
|
||||
@media (min-width: 768px) {
|
||||
.main-portal-content {
|
||||
padding: 34px;
|
||||
}
|
||||
.hero {
|
||||
padding: 45px;
|
||||
}
|
||||
.course-card img {
|
||||
height: 280px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.main-portal-content {
|
||||
margin-left: 18px;
|
||||
}
|
||||
padding: 4px 10px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="main-portal-content">
|
||||
<div class="main-portal-content p-3">
|
||||
<div class="container-fluid">
|
||||
|
||||
<!-- Hero Section -->
|
||||
<div class="hero">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-lg-9 col-md-8 text-start">
|
||||
<h1 class="fw-bold display-6 mb-2">Diploma in Automotive Engineering</h1>
|
||||
<p class="lead mb-4 small opacity-75">Welcome back! Continue your learning journey and complete all modules.</p>
|
||||
<a href="#" class="btn btn-continue px-4 py-2 fw-semibold shadow-sm">
|
||||
<i class="fa fa-play me-2"></i> Continue Learning
|
||||
<h3 class="fw-bold mb-4" style="color: var(--theme-navy);">My Assigned Courses</h3>
|
||||
|
||||
@if(count($courses) > 0)
|
||||
@foreach($courses as $courseId => $courseItems)
|
||||
@php
|
||||
$firstItem = $courseItems->first();
|
||||
@endphp
|
||||
|
||||
<!-- Course Title Block -->
|
||||
<div class="course-header mt-4">
|
||||
<h3 class="fw-bold mb-1">{{ $firstItem->course_title }}</h3>
|
||||
<p class="mb-0 opacity-75">{{ $firstItem->course_code }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Modules List under this Course -->
|
||||
<h5 class="fw-bold mb-3 ms-2" style="color: var(--theme-navy);">Modules</h5>
|
||||
|
||||
<div class="row g-3">
|
||||
@foreach($courseItems as $index => $module)
|
||||
@if($module->module_id)
|
||||
<div class="col-12">
|
||||
<div class="card module-card p-3 shadow-sm">
|
||||
<div class="d-flex justify-content-between align-items-start flex-wrap gap-2">
|
||||
<div>
|
||||
@if(!empty($module->semester))
|
||||
<span class="semester-badge mb-2 d-inline-block">
|
||||
Semester {{ $module->semester }}
|
||||
</span>
|
||||
@endif
|
||||
|
||||
<h6 class="fw-bold text-dark mb-1">
|
||||
Module {{ $index + 1 }}: {{ $module->module_title }}
|
||||
</h6>
|
||||
|
||||
<p class="text-muted small mb-0">
|
||||
{{ $module->module_description ?? 'No description provided.' }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<a href="#" class="btn btn-sm text-white px-3 py-2" style="background-color: var(--theme-red); border-radius: 6px;">
|
||||
View Content <i class="fa fa-chevron-right ms-1"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-4 text-center d-none d-md-block">
|
||||
<i class="fa-solid fa-car-side" style="font-size:100px; opacity:.2; color: var(--gold-accent);"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content Grid -->
|
||||
<div class="row g-4">
|
||||
|
||||
<!-- LEFT COLUMN: Course details & Modules -->
|
||||
<div class="col-lg-8 col-12">
|
||||
|
||||
<!-- Main Course Card -->
|
||||
<div class="card course-card">
|
||||
<img src="https://images.unsplash.com/photo-1486262715619-67b85e0b08d3?auto=format&fit=crop&w=1200&q=80" alt="Course Image">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex flex-wrap justify-content-between align-items-start gap-2 mb-3">
|
||||
<div>
|
||||
<h3 class="fw-bold text-dark mb-1">AE101</h3>
|
||||
<p class="text-muted small mb-0">
|
||||
<i class="fa-solid fa-building me-1" style="color: var(--purple-light);"></i> Automotive Engineering Department
|
||||
</p>
|
||||
</div>
|
||||
<span class="badge bg-dark px-3 py-2 rounded-pill">Diploma</span>
|
||||
</div>
|
||||
|
||||
<p class="text-secondary small lh-base">
|
||||
Master engine diagnostics, suspension systems, transmission technology, electrical systems and hybrid vehicle maintenance.
|
||||
</p>
|
||||
|
||||
<div class="mt-4">
|
||||
<div class="d-flex justify-content-between mb-2 small">
|
||||
<span class="text-dark fw-semibold">Overall Progress</span>
|
||||
<span class="fw-bold" style="color: var(--purple-main);">55%</span>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" style="width:55%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modules Header -->
|
||||
<div class="my-4">
|
||||
<h4 class="fw-bold text-dark">
|
||||
<i class="fa-solid fa-list-check me-2" style="color: var(--gold-accent);"></i> Course Modules
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
<!-- Modules Sub-Grid -->
|
||||
<div class="row g-4">
|
||||
<!-- Module 1 -->
|
||||
<div class="col-md-6 col-12">
|
||||
<div class="card module-card h-100">
|
||||
<div class="card-body p-4 d-flex flex-column justify-content-between">
|
||||
<div>
|
||||
<div class="d-flex justify-content-between align-items-start gap-2 mb-2">
|
||||
<h6 class="fw-bold text-dark mb-0">Engine Fundamentals</h6>
|
||||
<span class="status completed">Completed</span>
|
||||
</div>
|
||||
<p class="text-muted small">Learn engine parts and working principles.</p>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<button class="btn btn-purple w-100 btn-sm py-2">Review Module</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Module 2 -->
|
||||
<div class="col-md-6 col-12">
|
||||
<div class="card module-card h-100">
|
||||
<div class="card-body p-4 d-flex flex-column justify-content-between">
|
||||
<div>
|
||||
<div class="d-flex justify-content-between align-items-start gap-2 mb-2">
|
||||
<h6 class="fw-bold text-dark mb-0">Transmission Systems</h6>
|
||||
<span class="status progressing">In Progress</span>
|
||||
</div>
|
||||
<p class="text-muted small">Manual & Automatic transmission systems.</p>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<button class="btn btn-gold w-100 btn-sm py-2">Continue Learning</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Module 3 -->
|
||||
<div class="col-md-6 col-12">
|
||||
<div class="card module-card h-100">
|
||||
<div class="card-body p-4 d-flex flex-column justify-content-between">
|
||||
<div>
|
||||
<div class="d-flex justify-content-between align-items-start gap-2 mb-2">
|
||||
<h6 class="fw-bold text-secondary mb-0">Brake Systems</h6>
|
||||
<span class="status locked"><i class="fa fa-lock me-1"></i> Locked</span>
|
||||
</div>
|
||||
<p class="text-muted small">Complete previous module to unlock.</p>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<button class="btn btn-secondary w-100 btn-sm py-2" disabled>Locked</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Module 4 -->
|
||||
<div class="col-md-6 col-12">
|
||||
<div class="card module-card h-100">
|
||||
<div class="card-body p-4 d-flex flex-column justify-content-between">
|
||||
<div>
|
||||
<div class="d-flex justify-content-between align-items-start gap-2 mb-2">
|
||||
<h6 class="fw-bold text-secondary mb-0">Hybrid Technology</h6>
|
||||
<span class="status locked"><i class="fa fa-lock me-1"></i> Locked</span>
|
||||
</div>
|
||||
<p class="text-muted small">Learn EV and Hybrid systems.</p>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<button class="btn btn-secondary w-100 btn-sm py-2" disabled>Locked</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- RIGHT COLUMN: Sidebar Statistics -->
|
||||
<div class="col-lg-4 col-12">
|
||||
<div class="row g-3">
|
||||
@else
|
||||
<div class="col-12">
|
||||
<div class="info-box d-flex align-items-center">
|
||||
<div class="stat-icon"><i class="fa fa-book"></i></div>
|
||||
<div class="ms-3">
|
||||
<h5 class="fw-bold mb-0" style="color: var(--purple-dark);">12</h5>
|
||||
<span class="text-muted small">Modules Available</span>
|
||||
<div class="alert alert-light border">No modules found for this course.</div>
|
||||
</div>
|
||||
@endif
|
||||
@endforeach
|
||||
</div>
|
||||
@endforeach
|
||||
@else
|
||||
<div class="bg-white p-5 text-center rounded-3 border">
|
||||
<i class="fas fa-book-open fa-3x text-muted mb-3"></i>
|
||||
<h5 class="fw-bold">No Courses Assigned</h5>
|
||||
<p class="text-muted mb-0">There are no courses currently assigned to your profile.</p>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="info-box d-flex align-items-center">
|
||||
<div class="stat-icon"><i class="fa fa-clock"></i></div>
|
||||
<div class="ms-3">
|
||||
<h5 class="fw-bold mb-0" style="color: var(--purple-dark);">2 Years</h5>
|
||||
<span class="text-muted small">Course Duration</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="info-box d-flex align-items-center">
|
||||
<div class="stat-icon"><i class="fa fa-award"></i></div>
|
||||
<div class="ms-3">
|
||||
<h5 class="fw-bold mb-0" style="color: var(--purple-dark);">NVQ Level 5</h5>
|
||||
<span class="text-muted small">Qualification</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div> <!-- End Row -->
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
@endsection
|
||||
|
|
@ -2,89 +2,144 @@
|
|||
|
||||
@section('content')
|
||||
<style>
|
||||
.profile-card {
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08) !important;
|
||||
background: #ffffff;
|
||||
}
|
||||
.profile-header {
|
||||
|
||||
background: linear-gradient(135deg, #3d0c3d 0%, #5c1d5c 100%);
|
||||
padding: 1.25rem 1.5rem;
|
||||
border-top-left-radius: 12px !important;
|
||||
border-top-right-radius: 12px !important;
|
||||
:root {
|
||||
--primary-navy: #0F2C59;
|
||||
--accent-red: #822424;
|
||||
--accent-red-hover: #6a2525;
|
||||
--bg-light: #F4F6F9;
|
||||
--text-main: #1E293B;
|
||||
--text-muted: #64748B;
|
||||
--border-color: rgba(15, 44, 89, 0.1);
|
||||
}
|
||||
|
||||
.profile-card {
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 10px 30px rgba(15, 44, 89, 0.08) !important;
|
||||
background: #ffffff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.profile-header {
|
||||
background: linear-gradient(135deg, var(--primary-navy) 0%, #1a3d73 100%);
|
||||
padding: 1.5rem 1.75rem;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.profile-info-row {
|
||||
padding: 0.9rem 0;
|
||||
border-bottom: 1px solid #f1f1f4;
|
||||
padding: 1.1rem 0;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.profile-info-row:hover {
|
||||
background-color: #f8fafc;
|
||||
}
|
||||
|
||||
.profile-info-row:last-of-type {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.profile-label {
|
||||
color: #6c757d;
|
||||
color: var(--text-muted);
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.profile-value {
|
||||
color: #212529;
|
||||
font-weight: 500;
|
||||
font-size: 0.95rem;
|
||||
color: var(--text-main);
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* ===== Theme Buttons ===== */
|
||||
.btn-edit {
|
||||
background-color: #5c1d5c;
|
||||
color: white;
|
||||
border-radius: 6px;
|
||||
padding: 0.5rem 1.5rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
background-color: var(--accent-red);
|
||||
color: #ffffff;
|
||||
border-radius: 30px;
|
||||
padding: 0.6rem 2rem;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn-edit:hover {
|
||||
background-color: #3d0c3d;
|
||||
color: white;
|
||||
box-shadow: 0 4px 10px rgba(92, 29, 92, 0.3);
|
||||
background-color: var(--accent-red-hover);
|
||||
color: #ffffff;
|
||||
box-shadow: 0 6px 15px rgba(130, 36, 36, 0.3);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.btn-save {
|
||||
background-color: var(--accent-red);
|
||||
color: #ffffff;
|
||||
border-radius: 6px;
|
||||
font-weight: 600;
|
||||
padding: 0.5rem 1.5rem;
|
||||
border: none;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-save:hover {
|
||||
background-color: var(--accent-red-hover);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Form & Input Enhancements */
|
||||
.form-control:focus {
|
||||
border-color: var(--primary-navy);
|
||||
box-shadow: 0 0 0 0.25rem rgba(15, 44, 89, 0.15);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container mt-5 mb-5">
|
||||
<div class="container py-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
|
||||
|
||||
{{-- Alert Success Message --}}
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible fade show mb-4" role="alert" style="border-radius: 8px;">
|
||||
<i class="bi bi-check-circle-fill me-2"></i> {{ session('success') }}
|
||||
<div class="alert alert-success alert-dismissible fade show mb-4 border-0 shadow-sm" role="alert" style="border-radius: 10px; background-color: #d1e7dd; color: #0f5132;">
|
||||
<i class="fa-solid fa-circle-check me-2"></i> {{ session('success') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
|
||||
{{-- Main Profile Card --}}
|
||||
<div class="card profile-card">
|
||||
|
||||
<!-- Purple Header -->
|
||||
<div class="card-header profile-header text-white">
|
||||
<h4 class="mb-0 fw-bold" style="font-size: 1.25rem;">User Profile Dashboard</h4>
|
||||
<!-- Navy Header -->
|
||||
<div class="card-header profile-header text-white d-flex align-items-center justify-content-between">
|
||||
<h4 class="mb-0 fw-bold" style="font-size: 1.25rem; letter-spacing: 0.02em;">
|
||||
<i class="fa-solid fa-user-gear me-2"></i>User Profile Dashboard
|
||||
</h4>
|
||||
<span class="badge bg-light text-dark fw-semibold px-3 py-2 rounded-pill small">Active Student</span>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-4">
|
||||
<!-- Name -->
|
||||
<div class="card-body p-4 p-md-5">
|
||||
|
||||
<!-- Full Name -->
|
||||
<div class="row profile-info-row align-items-center">
|
||||
<div class="col-md-4 profile-label">Full Name:</div>
|
||||
<div class="col-md-4 profile-label">
|
||||
<i class="fa-solid fa-id-card me-2 " style="color: #822424;"></i>Full Name:
|
||||
</div>
|
||||
<div class="col-md-8 profile-value">{{ $user->first_name . ' ' . $user->last_name }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Email -->
|
||||
<!-- Email Address -->
|
||||
<div class="row profile-info-row align-items-center">
|
||||
<div class="col-md-4 profile-label">Email Address:</div>
|
||||
<div class="col-md-4 profile-label">
|
||||
<i class="fa-solid fa-envelope me-2 " style="color: #822424;"></i>Email Address:
|
||||
</div>
|
||||
<div class="col-md-8 profile-value">{{ $user->email }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Phone -->
|
||||
<!-- Phone Number -->
|
||||
<div class="row profile-info-row align-items-center">
|
||||
<div class="col-md-4 profile-label">Phone Number:</div>
|
||||
<div class="col-md-4 profile-label">
|
||||
<i class="fa-solid fa-phone me-2 " style="color: #822424;"></i>Phone Number:
|
||||
</div>
|
||||
<div class="col-md-8 profile-value">
|
||||
{{ $user->phone ?? 'Not Provided' }}
|
||||
</div>
|
||||
|
|
@ -92,7 +147,9 @@
|
|||
|
||||
<!-- Created At -->
|
||||
<div class="row profile-info-row align-items-center">
|
||||
<div class="col-md-4 profile-label">Account Created:</div>
|
||||
<div class="col-md-4 profile-label">
|
||||
<i class="fa-solid fa-calendar-plus me-2 t " style="color: #822424;"></i>Account Created:
|
||||
</div>
|
||||
<div class="col-md-8 profile-value text-muted">
|
||||
{{ $user->created_at ? $user->created_at->format('Y-m-d H:i') : 'N/A' }}
|
||||
</div>
|
||||
|
|
@ -100,44 +157,42 @@
|
|||
|
||||
<!-- Updated At -->
|
||||
<div class="row profile-info-row align-items-center">
|
||||
<div class="col-md-4 profile-label">Last Updated:</div>
|
||||
<div class="col-md-4 profile-label">
|
||||
<i class="fa-solid fa-clock-rotate-left me-2 " style="color: #822424;"></i>Last Updated:
|
||||
</div>
|
||||
<div class="col-md-8 profile-value text-muted">
|
||||
{{ $user->updated_at ? $user->updated_at->format('Y-m-d H:i') : 'N/A' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit Button -->
|
||||
<div class="mt-4 text-end">
|
||||
<!-- <a href="#" class="btn btn-edit">Edit Profile</a> -->
|
||||
<div class="mt-4 text-end">
|
||||
<button type="button" class="btn btn-edit" data-bs-toggle="modal" data-bs-target="#editProfileModal">
|
||||
Edit Profile
|
||||
<!-- Edit Profile Trigger Button -->
|
||||
<div class="mt-4 pt-2 text-end">
|
||||
<button type="button" class="btn btn-edit shadow-sm" data-bs-toggle="modal" data-bs-target="#editProfileModal">
|
||||
<i class="fa-solid fa-pen-to-square me-2"></i>Edit Profile
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{{-- ===================== EDIT PROFILE MODAL ===================== --}}
|
||||
<div class="modal fade" id="editProfileModal" tabindex="-1" aria-labelledby="editProfileModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content" style="border-radius: 12px; overflow: hidden;">
|
||||
<div class="modal-content border-0 shadow-lg" style="border-radius: 16px; overflow: hidden;">
|
||||
|
||||
<!-- Modal Header (Oyage purple theme ekata match kala) -->
|
||||
<div class="modal-header text-white" style="background: linear-gradient(135deg, #3d0c3d 0%, #5c1d5c 100%);">
|
||||
<h5 class="modal-title fw-bold" id="editProfileModalLabel">Update Profile Details</h5>
|
||||
<!-- Modal Header (Navy Theme) -->
|
||||
<div class="modal-header text-white" style="background: linear-gradient(135deg, #0F2C59 0%, #1a3d73 100%);">
|
||||
<h5 class="modal-title fw-bold fs-6" id="editProfileModalLabel">
|
||||
<i class="fa-solid fa-user-pen me-2"></i>Update Profile Details
|
||||
</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Update Form -->
|
||||
<form action="{{ route('profile.update') }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
|
@ -146,31 +201,32 @@
|
|||
|
||||
<!-- First Name Input -->
|
||||
<div class="mb-3">
|
||||
<label for="first_name" class="form-label fw-bold" style="color: #6c757d;">First Name</label>
|
||||
<input type="text" class="form-control" id="first_name" name="first_name" value="{{ $user->first_name }}" required>
|
||||
<label for="first_name" class="form-label fw-semibold small" style="color: var(--text-muted);">First Name</label>
|
||||
<input type="text" class="form-control form-control-lg fs-6" id="first_name" name="first_name" value="{{ $user->first_name }}" required>
|
||||
</div>
|
||||
|
||||
<!-- Last Name Input -->
|
||||
<div class="mb-3">
|
||||
<label for="last_name" class="form-label fw-bold" style="color: #6c757d;">Last Name</label>
|
||||
<input type="text" class="form-control" id="last_name" name="last_name" value="{{ $user->last_name }}" required>
|
||||
<label for="last_name" class="form-label fw-semibold small" style="color: var(--text-muted);">Last Name</label>
|
||||
<input type="text" class="form-control form-control-lg fs-6" id="last_name" name="last_name" value="{{ $user->last_name }}" required>
|
||||
</div>
|
||||
|
||||
<!-- Phone Input -->
|
||||
<div class="mb-3">
|
||||
<label for="phone" class="form-label fw-bold" style="color: #6c757d;">Phone Number</label>
|
||||
<input type="text" class="form-control" id="phone" name="phone" value="{{ $user->phone }}">
|
||||
<label for="phone" class="form-label fw-semibold small" style="color: var(--text-muted);">Phone Number</label>
|
||||
<input type="text" class="form-control form-control-lg fs-6" id="phone" name="phone" value="{{ $user->phone }}">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Modal Footer Buttons -->
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn text-white" style="background-color: #5c1d5c;">Save Changes</button>
|
||||
<!-- Modal Footer -->
|
||||
<div class="modal-footer bg-light px-4">
|
||||
<button type="button" class="btn btn-secondary border-0 rounded-3" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-save rounded-3">Save Changes</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -4,525 +4,420 @@
|
|||
|
||||
@section('content')
|
||||
|
||||
<!-- Bootstrap 5 -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<!-- Google Font -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- html2pdf Library for Client-side PDF Generation -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--theme-navy: #2D355B; /* Primary Navy */
|
||||
--theme-navy-dark: #1F2541; /* Dark Navy */
|
||||
--theme-red: #822424; /* Primary Accent Red */
|
||||
--theme-red-hover: #df2c3e; /* Red Hover */
|
||||
--theme-yellow: #FFEA85; /* Accent Yellow/Gold */
|
||||
--bg-light: #F6F6F6; /* Page Background */
|
||||
--white: #ffffff;
|
||||
}
|
||||
|
||||
body {
|
||||
background:#f6f7fb;
|
||||
font-family: 'Poppins', sans-serif;
|
||||
background: var(--bg-light);
|
||||
}
|
||||
|
||||
/* =======================
|
||||
Hero
|
||||
Hero Section
|
||||
======================= */
|
||||
|
||||
.result-hero {
|
||||
|
||||
background:linear-gradient(135deg,#5E244E,#4a1c3e);
|
||||
color:#fff;
|
||||
border-radius:20px;
|
||||
padding:40px;
|
||||
background: linear-gradient(135deg, #2B293F 0%, #94A6F959 100%) !important;
|
||||
color: var(--white);
|
||||
border-radius: 16px;
|
||||
padding: 35px 30px;
|
||||
margin-bottom: 30px;
|
||||
box-shadow:0 15px 35px rgba(0,0,0,.15);
|
||||
|
||||
box-shadow: 0 8px 25px rgba(31, 37, 65, 0.15);
|
||||
border-left: 5px solid var(--theme-red);
|
||||
}
|
||||
|
||||
.result-hero h2 {
|
||||
|
||||
font-weight: 700;
|
||||
|
||||
}
|
||||
|
||||
.result-hero p {
|
||||
|
||||
color:#ddd;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
margin-bottom: 0;
|
||||
|
||||
}
|
||||
|
||||
/* =======================
|
||||
Summary Cards
|
||||
======================= */
|
||||
|
||||
.summary-card {
|
||||
|
||||
background:#fff;
|
||||
border:none;
|
||||
border-radius:20px;
|
||||
background: var(--white);
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 16px;
|
||||
padding: 25px;
|
||||
text-align: center;
|
||||
box-shadow:0 10px 25px rgba(0,0,0,.08);
|
||||
transition:.3s;
|
||||
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, .04);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.summary-card:hover {
|
||||
|
||||
transform:translateY(-5px);
|
||||
|
||||
transform: translateY(-4px);
|
||||
border-color: var(--theme-navy);
|
||||
box-shadow: 0 10px 22px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.summary-card i {
|
||||
|
||||
font-size:40px;
|
||||
color:#5E244E;
|
||||
margin-bottom:15px;
|
||||
|
||||
font-size: 36px;
|
||||
color: var(--theme-red);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.summary-card h3 {
|
||||
|
||||
color:#5E244E;
|
||||
color: var(--theme-navy);
|
||||
font-weight: 700;
|
||||
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.summary-card small {
|
||||
|
||||
color:#777;
|
||||
|
||||
color: #64748b;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* =======================
|
||||
Result Table
|
||||
======================= */
|
||||
|
||||
.result-card {
|
||||
|
||||
margin-top:35px;
|
||||
background:#fff;
|
||||
border-radius:20px;
|
||||
margin-top: 30px;
|
||||
background: var(--white);
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
box-shadow:0 10px 30px rgba(0,0,0,.08);
|
||||
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, .04);
|
||||
}
|
||||
|
||||
.table-head {
|
||||
|
||||
background:#5E244E;
|
||||
color:#fff;
|
||||
background: var(--theme-navy);
|
||||
color: var(--white);
|
||||
padding: 18px 25px;
|
||||
|
||||
}
|
||||
|
||||
.table {
|
||||
|
||||
margin-bottom: 0;
|
||||
|
||||
}
|
||||
|
||||
.table th {
|
||||
|
||||
background:#744a68;
|
||||
color:#fff;
|
||||
border:none;
|
||||
|
||||
background: #f8fafc;
|
||||
color: var(--theme-navy);
|
||||
font-weight: 600;
|
||||
border-bottom: 2px solid #e2e8f0;
|
||||
padding: 14px 20px;
|
||||
}
|
||||
|
||||
.table td {
|
||||
|
||||
vertical-align: middle;
|
||||
|
||||
padding: 14px 20px;
|
||||
}
|
||||
|
||||
.grade {
|
||||
|
||||
padding:7px 15px;
|
||||
padding: 5px 14px;
|
||||
border-radius: 30px;
|
||||
font-weight: 600;
|
||||
color:#fff;
|
||||
font-size: 13px;
|
||||
color: var(--white);
|
||||
display: inline-block;
|
||||
|
||||
}
|
||||
|
||||
.a{
|
||||
|
||||
background:#28a745;
|
||||
|
||||
.grade.a {
|
||||
background: var(--theme-navy);
|
||||
}
|
||||
|
||||
.b{
|
||||
|
||||
background:#17a2b8;
|
||||
|
||||
.grade.b {
|
||||
background: var(--theme-red);
|
||||
}
|
||||
|
||||
.c{
|
||||
|
||||
background:#ffc107;
|
||||
color:#222;
|
||||
|
||||
.grade.c {
|
||||
background: #e67e22;
|
||||
}
|
||||
|
||||
.fail{
|
||||
|
||||
.grade.fail {
|
||||
background: #dc3545;
|
||||
}
|
||||
|
||||
.status-pass {
|
||||
color: #198754;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.status-fail {
|
||||
color: #dc3545;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* =======================
|
||||
Progress
|
||||
======================= */
|
||||
|
||||
.progress {
|
||||
|
||||
height: 10px;
|
||||
border-radius: 20px;
|
||||
background-color: #e2e8f0;
|
||||
}
|
||||
|
||||
.progress-bar-navy {
|
||||
background-color: var(--theme-navy) !important;
|
||||
}
|
||||
|
||||
.progress-bar-red {
|
||||
background-color: var(--theme-red) !important;
|
||||
}
|
||||
|
||||
.align-items-stretch {
|
||||
align-items: stretch !important;
|
||||
padding-top: 38px;
|
||||
}
|
||||
|
||||
/* =======================
|
||||
Download
|
||||
Download Card
|
||||
======================= */
|
||||
|
||||
.download-card {
|
||||
|
||||
margin-top: 30px;
|
||||
background:#4a1c3e;
|
||||
color:#fff;
|
||||
border-radius:20px;
|
||||
background: linear-gradient(135deg, #2B293F 0%, #94A6F959 100%) !important;
|
||||
color: var(--white);
|
||||
border-radius: 16px;
|
||||
padding: 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
gap: 15px;
|
||||
box-shadow: 0 8px 25px rgba(31, 37, 65, 0.15);
|
||||
}
|
||||
|
||||
.download-card h4 {
|
||||
|
||||
color:#d4af37;
|
||||
color: var(--theme-yellow);
|
||||
font-weight: 700;
|
||||
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.btn-result {
|
||||
|
||||
background:#d4af37;
|
||||
color:#fff;
|
||||
background-color: var(--theme-red) !important;
|
||||
color: var(--white) !important;
|
||||
border: none;
|
||||
border-radius:50px;
|
||||
padding:12px 30px;
|
||||
border-radius: 8px;
|
||||
padding: 10px 24px;
|
||||
font-weight: 600;
|
||||
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-result:hover {
|
||||
|
||||
background:#c49d20;
|
||||
color:#fff;
|
||||
|
||||
background-color: var(--theme-red-hover) !important;
|
||||
color: var(--white) !important;
|
||||
}
|
||||
|
||||
@media(max-width:768px) {
|
||||
.result-hero {
|
||||
padding: 25px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container py-4">
|
||||
|
||||
<!-- Hero -->
|
||||
<!-- Printable Area Container -->
|
||||
<div id="pdf-download-area">
|
||||
|
||||
<!-- Hero Section -->
|
||||
<div class="result-hero">
|
||||
|
||||
<h2>
|
||||
|
||||
<i class="fas fa-award"></i>
|
||||
|
||||
<i class="fas fa-award me-2" style="color: var(--theme-yellow);"></i>
|
||||
Academic Results
|
||||
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
|
||||
View your examination results and academic performance.
|
||||
|
||||
View your examination results and overall academic performance.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Summary -->
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-4 mb-4">
|
||||
|
||||
<!-- Summary Cards -->
|
||||
<div class="row g-4">
|
||||
<div class="col-md-4">
|
||||
<div class="summary-card">
|
||||
|
||||
<i class="fas fa-chart-line"></i>
|
||||
|
||||
<h3>82%</h3>
|
||||
|
||||
<h3>{{ $averageMarks ?? 0 }}%</h3>
|
||||
<small>Overall Average</small>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 mb-4">
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="summary-card">
|
||||
|
||||
<i class="fas fa-medal"></i>
|
||||
|
||||
<h3>3.65</h3>
|
||||
|
||||
<h3>{{ $gpa ?? '3.65' }}</h3>
|
||||
<small>Current GPA</small>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 mb-4">
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="summary-card">
|
||||
|
||||
<i class="fas fa-book"></i>
|
||||
|
||||
<h3>6 / 6</h3>
|
||||
|
||||
<i class="fas fa-book-open"></i>
|
||||
<h3>{{ $passedModules ?? 0 }} / {{ $totalModules ?? 0 }}</h3>
|
||||
<small>Modules Passed</small>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Result Table -->
|
||||
|
||||
<div class="result-card">
|
||||
|
||||
<div class="table-head">
|
||||
|
||||
<h4 class="mb-0">
|
||||
|
||||
<div class="table-head d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0 fw-bold">
|
||||
Semester Results
|
||||
|
||||
</h4>
|
||||
|
||||
</h5>
|
||||
@if(isset($results) && $results->isNotEmpty())
|
||||
<span class="badge bg-light text-dark">
|
||||
{{ optional($results->first())->academic_year }} | {{ optional($results->first())->semester }}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<table class="table table-hover">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
|
||||
<tr>
|
||||
|
||||
<th>Module</th>
|
||||
<th>Module Code</th>
|
||||
<th>Module Name</th>
|
||||
<th>Marks</th>
|
||||
<th>Grade</th>
|
||||
<th>Status</th>
|
||||
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
@forelse ($results ?? [] as $item)
|
||||
<tr>
|
||||
|
||||
<td>Engine Technology</td>
|
||||
|
||||
<td>91</td>
|
||||
|
||||
<td class="fw-bold" style="color: var(--theme-navy);">{{ $item->module_code }}</td>
|
||||
<td class="fw-semibold">{{ $item->module_name }}</td>
|
||||
<td>{{ $item->marks }}</td>
|
||||
<td>
|
||||
@php
|
||||
$gradeClass = 'b';
|
||||
$upperGrade = strtoupper($item->grade ?? '');
|
||||
|
||||
<span class="grade a">
|
||||
|
||||
A+
|
||||
|
||||
</span>
|
||||
|
||||
if(str_contains($upperGrade, 'A')) {
|
||||
$gradeClass = 'a';
|
||||
} elseif(str_contains($upperGrade, 'F')) {
|
||||
$gradeClass = 'fail';
|
||||
} elseif(str_contains($upperGrade, 'C')) {
|
||||
$gradeClass = 'c';
|
||||
}
|
||||
@endphp
|
||||
<span class="grade {{ $gradeClass }}">{{ $item->grade }}</span>
|
||||
</td>
|
||||
<td>
|
||||
@if(strtolower($item->status ?? '') == 'pass')
|
||||
<span class="status-pass"><i class="fas fa-check-circle me-1"></i>Pass</span>
|
||||
@else
|
||||
<span class="status-fail"><i class="fas fa-times-circle me-1"></i>Fail</span>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
<td>Pass</td>
|
||||
|
||||
</tr>
|
||||
|
||||
@empty
|
||||
<tr>
|
||||
|
||||
<td>Brake Systems</td>
|
||||
|
||||
<td>84</td>
|
||||
|
||||
<td>
|
||||
|
||||
<span class="grade a">
|
||||
|
||||
A
|
||||
|
||||
</span>
|
||||
|
||||
<td colspan="5" class="text-center py-4 text-muted">
|
||||
<i class="fas fa-info-circle me-1"></i> No result records found for your account.
|
||||
</td>
|
||||
|
||||
<td>Pass</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
<td>Electrical Systems</td>
|
||||
|
||||
<td>79</td>
|
||||
|
||||
<td>
|
||||
|
||||
<span class="grade b">
|
||||
|
||||
B+
|
||||
|
||||
</span>
|
||||
|
||||
</td>
|
||||
|
||||
<td>Pass</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
<td>Transmission Systems</td>
|
||||
|
||||
<td>74</td>
|
||||
|
||||
<td>
|
||||
|
||||
<span class="grade b">
|
||||
|
||||
B
|
||||
|
||||
</span>
|
||||
|
||||
</td>
|
||||
|
||||
<td>Pass</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
<td>Workshop Practice</td>
|
||||
|
||||
<td>88</td>
|
||||
|
||||
<td>
|
||||
|
||||
<span class="grade a">
|
||||
|
||||
A
|
||||
|
||||
</span>
|
||||
|
||||
</td>
|
||||
|
||||
<td>Pass</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
<td>Industrial Safety</td>
|
||||
|
||||
<td>81</td>
|
||||
|
||||
<td>
|
||||
|
||||
<span class="grade a">
|
||||
|
||||
A-
|
||||
|
||||
</span>
|
||||
|
||||
</td>
|
||||
|
||||
<td>Pass</td>
|
||||
|
||||
</tr>
|
||||
|
||||
@endforelse
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Performance -->
|
||||
|
||||
<div class="result-card mt-4">
|
||||
<!-- Performance & Download Section (Side by Side) -->
|
||||
<div class="row g-4 align-items-stretch">
|
||||
|
||||
<!-- Overall Performance Card -->
|
||||
<div class="col-md-6">
|
||||
<div class="result-card h-100 mt-0">
|
||||
<div class="table-head">
|
||||
|
||||
<h4 class="mb-0">
|
||||
|
||||
<h5 class="mb-0 fw-bold">
|
||||
Overall Performance
|
||||
|
||||
</h4>
|
||||
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div class="p-4">
|
||||
|
||||
<p class="mb-2">
|
||||
|
||||
Course Completion
|
||||
|
||||
</p>
|
||||
|
||||
<div class="p-4 d-flex flex-column justify-content-center">
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<span class="fw-semibold" style="color: var(--theme-navy);">Course Completion</span>
|
||||
<span class="fw-bold" style="color: var(--theme-navy);">{{ $averageMarks ?? 0 }}%</span>
|
||||
</div>
|
||||
<div class="progress mb-4">
|
||||
|
||||
<div class="progress-bar bg-success"
|
||||
|
||||
style="width:82%">
|
||||
|
||||
<div class="progress-bar progress-bar-navy" style="width: {{ $averageMarks ?? 0 }}%"></div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<span class="fw-semibold" style="color: var(--theme-navy);">Attendance Score</span>
|
||||
<span class="fw-bold" style="color: var(--theme-red);">90%</span>
|
||||
</div>
|
||||
|
||||
<p class="mb-2">
|
||||
|
||||
Attendance Score
|
||||
|
||||
</p>
|
||||
|
||||
<div class="progress">
|
||||
|
||||
<div class="progress-bar bg-warning"
|
||||
|
||||
style="width:90%">
|
||||
|
||||
<div class="progress-bar progress-bar-red" style="width: 90%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Download -->
|
||||
|
||||
<div class="download-card">
|
||||
|
||||
<!-- Download Section Card -->
|
||||
<div class="col-md-6">
|
||||
<div class="download-card h-100 mt-0 flex-column justify-content-between align-items-start text-start">
|
||||
<div>
|
||||
|
||||
<h4>
|
||||
|
||||
Download Official Result Sheet
|
||||
|
||||
</h4>
|
||||
|
||||
<p class="mb-0">
|
||||
|
||||
Download your latest semester examination results in PDF format.
|
||||
|
||||
<h4 class="mb-3">Download Official Result Sheet</h4>
|
||||
<p class="mb-4">
|
||||
Get your latest semester examination results in official PDF format.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<button class="btn btn-result">
|
||||
|
||||
<i class="fas fa-download"></i>
|
||||
|
||||
Download PDF
|
||||
|
||||
<button id="download-pdf-btn" onclick="generatePDF()" class="btn btn-result shadow-sm w-100">
|
||||
<i class="fas fa-download me-2"></i>Download PDF
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- JavaScript to handle PDF Download -->
|
||||
<script>
|
||||
function generatePDF() {
|
||||
const element = document.getElementById('pdf-download-area');
|
||||
const button = document.getElementById('download-pdf-btn');
|
||||
|
||||
|
||||
button.disabled = true;
|
||||
button.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Generating PDF...';
|
||||
|
||||
const options = {
|
||||
margin: [10, 10, 10, 10],
|
||||
filename: 'Official_Result_Sheet.pdf',
|
||||
image: { type: 'jpeg', quality: 0.98 },
|
||||
html2canvas: { scale: 2, useCORS: true },
|
||||
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }
|
||||
};
|
||||
|
||||
|
||||
html2pdf().set(options).from(element).save().then(() => {
|
||||
button.disabled = false;
|
||||
button.innerHTML = '<i class="fas fa-download me-2"></i>Download PDF';
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
button.disabled = false;
|
||||
button.innerHTML = '<i class="fas fa-download me-2"></i>Download PDF';
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
|
|
@ -3,26 +3,51 @@
|
|||
@section('title', 'Student Login')
|
||||
|
||||
@push('styles')
|
||||
<!-- Google Font -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: #f5f7fb;
|
||||
:root {
|
||||
--theme-navy: #2D355B; /* Primary Navy */
|
||||
--theme-navy-dark: #1F2541; /* Dark Navy */
|
||||
--theme-red: #822424; /* Primary Accent Red */
|
||||
--theme-red-hover: #df2c3e; /* Red Hover */
|
||||
--theme-yellow: #FFEA85; /* Accent Yellow/Gold */
|
||||
--bg-light: #F6F6F6; /* Page Background */
|
||||
--white: #ffffff;
|
||||
}
|
||||
* {
|
||||
font-family: 'Arial', Helvetica, sans-serif;
|
||||
transform: scale(0.95);
|
||||
|
||||
body {
|
||||
background: var(--bg-light);
|
||||
font-family: 'Poppins', sans-serif;
|
||||
}
|
||||
|
||||
/* LEFT PANEL */
|
||||
.left-panel {
|
||||
min-height: 100vh;
|
||||
background: #f8f9fa;
|
||||
background: linear-gradient(135deg, var(--theme-navy) 0%, var(--theme-navy-dark) 100%);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--white);
|
||||
border-right: 5px solid var(--theme-red);
|
||||
}
|
||||
|
||||
.left-panel img {
|
||||
max-width: 450px;
|
||||
max-width: 400px;
|
||||
filter: drop-shadow(0 10px 15px rgba(0,0,0,0.3));
|
||||
}
|
||||
|
||||
.left-panel h2 {
|
||||
color: var(--white);
|
||||
font-size: 28px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.left-panel p {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
/* RIGHT PANEL */
|
||||
|
|
@ -32,106 +57,103 @@
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 40px;
|
||||
background: var(--bg-light);
|
||||
scale: 0.7;
|
||||
}
|
||||
|
||||
/* LOGIN BOX */
|
||||
.box {
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
background: #ffffff;
|
||||
padding: 45px;
|
||||
border-radius: 18px;
|
||||
box-shadow: 0 15px 40px rgba(0,0,0,0.12);
|
||||
max-width: 480px;
|
||||
background: var(--white);
|
||||
padding: 45px 40px;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 10px 30px rgba(31, 37, 65, 0.08);
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
/* TITLE */
|
||||
.headline {
|
||||
text-align: center;
|
||||
font-size: 32px;
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: #222;
|
||||
color: var(--theme-navy);
|
||||
margin-bottom: 35px;
|
||||
}
|
||||
|
||||
/* INPUT */
|
||||
/* INPUT CONTAINER */
|
||||
.input-container {
|
||||
position: relative;
|
||||
margin-bottom: 25px;
|
||||
font-size: 22px;
|
||||
font-family: arial;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.input-container input {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
padding: 12px 0;
|
||||
height: 48px;
|
||||
padding: 10px 0 5px 0;
|
||||
border: none;
|
||||
border-bottom: 2px solid #ddd;
|
||||
border-bottom: 2px solid #cbd5e1;
|
||||
background: transparent;
|
||||
outline: none;
|
||||
font-size: 22px;
|
||||
font-family: arial;
|
||||
|
||||
font-size: 16px;
|
||||
color: #1e293b;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.input-container label {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
top: 12px;
|
||||
left: 0;
|
||||
color: #744a68;
|
||||
transition: .3s;
|
||||
color: #64748b;
|
||||
transition: 0.3s ease;
|
||||
pointer-events: none;
|
||||
font-size: 22px;
|
||||
font-family: arial;
|
||||
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
/* FLOATING LABEL & VALIDATION STATES */
|
||||
.input-container input:focus,
|
||||
.input-container input:valid {
|
||||
border-bottom-color: #744a68;
|
||||
font-size: 20px;
|
||||
font-family: arial;
|
||||
.input-container input:focus {
|
||||
border-bottom-color: var(--theme-navy);
|
||||
}
|
||||
|
||||
.input-container input:focus + label,
|
||||
.input-container input:not(:placeholder-shown) + label {
|
||||
top: -12px;
|
||||
font-size: 12px;
|
||||
color: #744a68;
|
||||
color: var(--theme-navy);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* FORGOT PASSWORD */
|
||||
.forgot-link {
|
||||
color: #744a68;
|
||||
font-size: 16px;
|
||||
color: var(--theme-red);
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
padding-left: 37%;
|
||||
transition: color 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.forgot-link:hover {
|
||||
text-decoration: underline;
|
||||
color: #5E244E;
|
||||
color: var(--theme-red-hover);
|
||||
}
|
||||
|
||||
/* BUTTON */
|
||||
.btn-primary {
|
||||
height: 50px;
|
||||
height: 48px;
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
background: #5E244E;
|
||||
background: var(--theme-red) !important;
|
||||
border: none;
|
||||
color: white;
|
||||
/* border-radius: 8px; */
|
||||
transition: background 0.2s ease-in-out, transform 0.1s ease;
|
||||
color: var(--white) !important;
|
||||
border-radius: 8px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-primary:hover, .btn-primary:focus {
|
||||
background: #4a1c3e;
|
||||
color: white;
|
||||
background: #822424 !important;
|
||||
box-shadow: 0 4px 12px rgba(130, 36, 36, 0.3);
|
||||
}
|
||||
|
||||
.btn-primary:active {
|
||||
|
|
@ -141,25 +163,28 @@
|
|||
/* BOTTOM TEXT */
|
||||
.dontacc {
|
||||
text-align: center;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.dontacc p {
|
||||
color: #666;
|
||||
color: #64748b;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.dontacc a {
|
||||
color: #744a68;
|
||||
color: var(--theme-navy);
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
font-family: arial;
|
||||
font-size: 15px;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.dontacc a:hover {
|
||||
text-decoration: underline;
|
||||
color: var(--theme-navy-dark);
|
||||
}
|
||||
|
||||
/* RESPONSIVE DESIGN */
|
||||
|
||||
@media(max-width:991px) {
|
||||
.left-panel {
|
||||
display: none !important;
|
||||
|
|
@ -171,16 +196,38 @@
|
|||
}
|
||||
|
||||
.box {
|
||||
padding: 30px;
|
||||
padding: 35px 25px;
|
||||
}
|
||||
|
||||
.headline {
|
||||
font-size: 28px;
|
||||
color: #5E244E;
|
||||
font-weight: bold;
|
||||
font-family: Arial;
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.input-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
.toggle-password {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 15px;
|
||||
cursor: pointer;
|
||||
color: #744a68;
|
||||
z-index: 10;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.toggle-password:hover {
|
||||
color: #5E244E;
|
||||
}
|
||||
|
||||
|
||||
.input-container input {
|
||||
padding-right: 35px !important;
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
|
|
@ -188,17 +235,9 @@
|
|||
<div class="container-fluid">
|
||||
<div class="row min-vh-100">
|
||||
|
||||
<!-- <div class="col-lg-6 left-panel">
|
||||
<div class="text-center">
|
||||
<img src="{{ asset('images/login-banner.png') }}" class="img-fluid mb-4" alt="Automobile Engineering Academy">
|
||||
<h2 class="fw-bold">Automobile Engineering Academy</h2>
|
||||
<p class="text-muted px-5">
|
||||
Driving Innovation Through Education, Research and Technology.
|
||||
</p>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="col-lg-6 right-panel">
|
||||
|
||||
<div class="col-lg-6 right-panel col-12 mx-auto">
|
||||
<div class="box">
|
||||
<h2 class="headline">Student Sign In</h2>
|
||||
|
||||
|
|
@ -213,9 +252,18 @@
|
|||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="input-container">
|
||||
<!-- <div class="input-container">
|
||||
<input type="password" name="password" placeholder=" " required>
|
||||
<label>Password</label>
|
||||
@error('password')
|
||||
<span class="d-block text-danger mt-1 small">{{ $message }}</span>
|
||||
@enderror
|
||||
</div> -->
|
||||
<div class="input-container">
|
||||
<input type="password" id="password" name="password" placeholder=" " required>
|
||||
<label>Password</label>
|
||||
<i class="fa-solid fa-eye toggle-password" id="togglePassword"></i>
|
||||
|
||||
@error('password')
|
||||
<span class="d-block text-danger mt-1 small">{{ $message }}</span>
|
||||
@enderror
|
||||
|
|
@ -223,15 +271,14 @@
|
|||
|
||||
|
||||
|
||||
<button type="submit" class="btn btn-primary mb-4">
|
||||
<button type="submit" class="btn btn-primary mb-4 shadow-sm">
|
||||
Sign In
|
||||
</button>
|
||||
|
||||
<div class="d-flex justify-content-end mb-4" style="gap: 10px;padding-top: 10px; padding-left: 190px;">
|
||||
<div class="d-flex justify-content-end mb-4">
|
||||
<a href="{{ url('/password/reset') }}" class="forgot-link">Forgot Password?</a>
|
||||
</div>
|
||||
|
||||
<div class="dontacc" style="padding-top: 10px; " >
|
||||
<div class="dontacc">
|
||||
<!-- <p class="mb-1">Don't have an account?</p> -->
|
||||
<a href="{{ url('/signup') }}">Create Student Account</a>
|
||||
</div>
|
||||
|
|
@ -243,3 +290,19 @@
|
|||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const togglePassword = document.getElementById('togglePassword');
|
||||
const passwordInput = document.getElementById('password');
|
||||
|
||||
togglePassword.addEventListener('click', function () {
|
||||
|
||||
const type = passwordInput.getAttribute('type') === 'password' ? 'text' : 'password';
|
||||
passwordInput.setAttribute('type', type);
|
||||
|
||||
|
||||
this.classList.toggle('fa-eye');
|
||||
this.classList.toggle('fa-eye-slash');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
@ -3,6 +3,9 @@
|
|||
@section('title', 'Student Registration')
|
||||
|
||||
@push('styles')
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<style>
|
||||
body {
|
||||
background: #f5f7fb;
|
||||
|
|
@ -10,7 +13,7 @@
|
|||
scale: 0.92;
|
||||
}
|
||||
|
||||
/* LEFT PANEL (If active) */
|
||||
|
||||
.left-panel {
|
||||
background: #5E244E;
|
||||
color: white;
|
||||
|
|
@ -20,7 +23,6 @@
|
|||
padding: 40px;
|
||||
}
|
||||
|
||||
/* RIGHT PANEL */
|
||||
.right-panel {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
|
|
@ -37,9 +39,9 @@
|
|||
padding: 45px;
|
||||
border-radius: 18px;
|
||||
box-shadow: 0 15px 40px rgba(0,0,0,0.12);
|
||||
scale : 0.72
|
||||
}
|
||||
|
||||
/* TITLE */
|
||||
.headline {
|
||||
text-align: center;
|
||||
font-size: 32px;
|
||||
|
|
@ -48,7 +50,7 @@
|
|||
margin-bottom: 35px;
|
||||
}
|
||||
|
||||
/* MODERN INPUT WITH FLOATING LABELS */
|
||||
|
||||
.input-container {
|
||||
position: relative;
|
||||
margin-bottom: 25px;
|
||||
|
|
@ -57,7 +59,7 @@
|
|||
.input-container input {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
padding: 15px 0 5px 0;
|
||||
padding: 15px 35px 5px 0;
|
||||
border: none;
|
||||
border-bottom: 2px solid #ddd;
|
||||
background: transparent;
|
||||
|
|
@ -77,12 +79,12 @@
|
|||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Input Focus States */
|
||||
|
||||
.input-container input:focus {
|
||||
border-bottom-color: #744a68;
|
||||
}
|
||||
|
||||
/* Label Floating Effect */
|
||||
|
||||
.input-container input:focus + label,
|
||||
.input-container input:not(:placeholder-shown) + label {
|
||||
top: -10px;
|
||||
|
|
@ -91,6 +93,22 @@
|
|||
font-weight: 600;
|
||||
}
|
||||
|
||||
|
||||
.toggle-password {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 37px;
|
||||
cursor: pointer;
|
||||
color: #744a68;
|
||||
font-size: 16px;
|
||||
z-index: 10;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.toggle-password:hover {
|
||||
color: #5E244E;
|
||||
}
|
||||
|
||||
/* CHECKBOX STYLE */
|
||||
.form-check-input:checked {
|
||||
background-color: #5E244E;
|
||||
|
|
@ -109,14 +127,14 @@
|
|||
width: 100%;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
background: #5E244E;
|
||||
background: #822424;
|
||||
border: none;
|
||||
color: white;
|
||||
transition: background 0.2s ease-in-out, transform 0.1s ease;
|
||||
}
|
||||
|
||||
.btn-primary:hover, .btn-primary:focus {
|
||||
background: #4a1c3e;
|
||||
background: #822424;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +142,7 @@
|
|||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
/* BOTTOM TEXT */
|
||||
|
||||
.dontacc {
|
||||
text-align: center;
|
||||
}
|
||||
|
|
@ -147,6 +165,37 @@
|
|||
color: #5E244E;
|
||||
}
|
||||
|
||||
|
||||
.password-rules {
|
||||
display: none;
|
||||
margin-top: -15px;
|
||||
margin-bottom: 20px;
|
||||
padding: 10px 15px;
|
||||
background: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.password-rules ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.password-rules li {
|
||||
margin-bottom: 3px;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.rule-invalid {
|
||||
color: #dc3545; /* Red */
|
||||
}
|
||||
|
||||
.rule-valid {
|
||||
color: #198754; /* Green */
|
||||
}
|
||||
|
||||
@media(max-width:991px) {
|
||||
.right-panel {
|
||||
min-height: 100vh;
|
||||
|
|
@ -170,11 +219,12 @@
|
|||
<div class="container-fluid">
|
||||
<div class="row min-vh-100">
|
||||
|
||||
<div class="col-md-8 col-lg-5 mx-auto right-panel">
|
||||
<div class="col-md-8 col-lg-5 mx-auto right-panel" style="padding-left:5px;">
|
||||
<div class="box">
|
||||
<h2 class="headline">Student Registration</h2>
|
||||
|
||||
<form method="POST" action="{{ url('/signuppage') }}">
|
||||
|
||||
@csrf
|
||||
|
||||
<div class="input-container">
|
||||
|
|
@ -209,19 +259,38 @@
|
|||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="input-container">
|
||||
<input type="password" name="password" placeholder=" " required autocomplete="new-password">
|
||||
|
||||
<div class="input-container mb-2">
|
||||
<input type="password" id="password" name="password" placeholder=" " required autocomplete="new-password">
|
||||
<label>Password</label>
|
||||
<i class="fa-solid fa-eye toggle-password" id="togglePassword"></i>
|
||||
@error('password')
|
||||
<span class="d-block text-danger mt-1 small">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="input-container">
|
||||
<input type="password" name="password_confirmation" placeholder=" " required autocomplete="new-password">
|
||||
<label>Confirm Password</label>
|
||||
|
||||
<div class="password-rules" id="passwordRules">
|
||||
<strong style="font-size: 13px; color: #444;" class="d-block mb-1">Password Status:</strong>
|
||||
<ul>
|
||||
<li id="rule-length" class="rule-invalid">• At least 6 characters</li>
|
||||
<li id="rule-upper" class="rule-invalid">• At least one uppercase letter</li>
|
||||
<li id="rule-lower" class="rule-invalid">• At least one lowercase letter</li>
|
||||
<li id="rule-number" class="rule-invalid">• At least one number</li>
|
||||
<li id="rule-special" class="rule-invalid">• At least one special character</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="input-container mb-2">
|
||||
<input type="password" id="password_confirmation" name="password_confirmation" placeholder=" " required autocomplete="new-password">
|
||||
<label>Confirm Password</label>
|
||||
<i class="fa-solid fa-eye toggle-password" id="toggleConfirmPassword"></i>
|
||||
</div>
|
||||
|
||||
<!-- Confirm Password Match Status Message -->
|
||||
<div id="matchMessage" class="mb-3 small" style="display: none; font-weight: 600; font-size: 12px;"></div>
|
||||
|
||||
<div class="form-check mb-4 d-flex align-items-center gap-2">
|
||||
<input class="form-check-input" type="checkbox" id="agree" required>
|
||||
<label class="form-check-label" for="agree">
|
||||
|
|
@ -244,3 +313,96 @@
|
|||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const passwordInput = document.getElementById('password');
|
||||
const confirmPasswordInput = document.getElementById('password_confirmation');
|
||||
const passwordRules = document.getElementById('passwordRules');
|
||||
const matchMessage = document.getElementById('matchMessage');
|
||||
|
||||
const togglePassword = document.getElementById('togglePassword');
|
||||
const toggleConfirmPassword = document.getElementById('toggleConfirmPassword');
|
||||
|
||||
const ruleLength = document.getElementById('rule-length');
|
||||
const ruleUpper = document.getElementById('rule-upper');
|
||||
const ruleLower = document.getElementById('rule-lower');
|
||||
const ruleNumber = document.getElementById('rule-number');
|
||||
const ruleSpecial = document.getElementById('rule-special');
|
||||
|
||||
|
||||
function setupPasswordToggle(inputEl, iconEl) {
|
||||
iconEl.addEventListener('click', function () {
|
||||
const type = inputEl.getAttribute('type') === 'password' ? 'text' : 'password';
|
||||
inputEl.setAttribute('type', type);
|
||||
this.classList.toggle('fa-eye');
|
||||
this.classList.toggle('fa-eye-slash');
|
||||
});
|
||||
}
|
||||
|
||||
setupPasswordToggle(passwordInput, togglePassword);
|
||||
setupPasswordToggle(confirmPasswordInput, toggleConfirmPassword);
|
||||
|
||||
|
||||
|
||||
passwordInput.addEventListener('focus', function () {
|
||||
passwordRules.style.display = 'block';
|
||||
});
|
||||
|
||||
passwordInput.addEventListener('blur', function () {
|
||||
if (passwordInput.value.length === 0) {
|
||||
passwordRules.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
passwordInput.addEventListener('input', function () {
|
||||
const val = passwordInput.value;
|
||||
|
||||
toggleRule(ruleLength, val.length >= 6);
|
||||
toggleRule(ruleUpper, /[A-Z]/.test(val));
|
||||
toggleRule(ruleLower, /[a-z]/.test(val));
|
||||
toggleRule(ruleNumber, /[0-9]/.test(val));
|
||||
toggleRule(ruleSpecial, /[!@#$%^&*(),.?":{}|<>]/.test(val));
|
||||
|
||||
checkPasswordMatch();
|
||||
});
|
||||
|
||||
function toggleRule(element, isValid) {
|
||||
if (isValid) {
|
||||
element.classList.remove('rule-invalid');
|
||||
element.classList.add('rule-valid');
|
||||
} else {
|
||||
element.classList.remove('rule-valid');
|
||||
element.classList.add('rule-invalid');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
confirmPasswordInput.addEventListener('input', checkPasswordMatch);
|
||||
|
||||
function checkPasswordMatch() {
|
||||
const pwd = passwordInput.value;
|
||||
const confirmPwd = confirmPasswordInput.value;
|
||||
|
||||
if (confirmPwd.length === 0) {
|
||||
matchMessage.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
matchMessage.style.display = 'block';
|
||||
|
||||
if (pwd === confirmPwd) {
|
||||
matchMessage.style.color = '#198754'; // Green
|
||||
matchMessage.textContent = '✓ Passwords match';
|
||||
} else {
|
||||
matchMessage.style.color = '#dc3545'; // Red
|
||||
matchMessage.textContent = '✕ Passwords do not match';
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -4,382 +4,539 @@
|
|||
|
||||
@section('content')
|
||||
|
||||
<!-- Bootstrap 5 -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
|
||||
<!-- Google Font -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
body{
|
||||
font-family:'Poppins',sans-serif;
|
||||
background:#f4f7fc;
|
||||
:root {
|
||||
--theme-navy: #1E233E;
|
||||
--theme-navy-dark: #15182C;
|
||||
--theme-red: #822424;
|
||||
--theme-red-hover: #df2c3e;
|
||||
--theme-yellow: #FFEA85;
|
||||
--theme-bg: #F4F6F9;
|
||||
--text-dark: #1E293B;
|
||||
}
|
||||
|
||||
.page-header{
|
||||
background:linear-gradient(135deg,#9954b8,#4f3d5b));
|
||||
color:#fff;
|
||||
padding:45px;
|
||||
/* Page Header Hero */
|
||||
.timetable-hero {
|
||||
background: linear-gradient(135deg, #1E233E 0%, #2A1F3B 50%, #4A1A24 100%);
|
||||
border-radius: 20px;
|
||||
background-color: #5E244E;
|
||||
margin-bottom:30px;
|
||||
}
|
||||
|
||||
.page-header h2{
|
||||
font-weight:700;
|
||||
}
|
||||
|
||||
.page-header p{
|
||||
opacity:.9;
|
||||
}
|
||||
|
||||
.info-card{
|
||||
border:none;
|
||||
border-radius:15px;
|
||||
box-shadow:0 10px 30px rgba(0,0,0,.08);
|
||||
}
|
||||
|
||||
.table-card{
|
||||
background:#fff;
|
||||
border-radius:20px;
|
||||
box-shadow:0 10px 30px rgba(0,0,0,.08);
|
||||
padding: 32px 38px;
|
||||
margin-bottom: 28px;
|
||||
box-shadow: 0 12px 32px rgba(30, 35, 62, 0.16);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.table thead{
|
||||
background:#0d6efd;
|
||||
color:#fff;
|
||||
.timetable-hero::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
right: -10%;
|
||||
width: 350px;
|
||||
height: 350px;
|
||||
background: radial-gradient(circle, rgba(255, 234, 133, 0.15) 0%, rgba(255, 234, 133, 0) 70%);
|
||||
border-radius: 50%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.table td,
|
||||
.table th{
|
||||
text-align:center;
|
||||
vertical-align:middle;
|
||||
min-width:140px;
|
||||
.btn-print {
|
||||
background: #ffffff;
|
||||
color: #1E233E;
|
||||
font-weight: 700;
|
||||
padding: 11px 26px;
|
||||
border-radius: 50px;
|
||||
border: none;
|
||||
box-shadow: 0 6px 18px rgba(0,0,0,0.12);
|
||||
transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.badge-theory{
|
||||
background:#0d6efd;
|
||||
.btn-print:hover {
|
||||
background: var(--theme-yellow);
|
||||
color: #1E233E;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 10px 24px rgba(255, 234, 133, 0.4);
|
||||
}
|
||||
|
||||
.badge-practical{
|
||||
background:#198754;
|
||||
}
|
||||
|
||||
.badge-workshop{
|
||||
background:#fd7e14;
|
||||
}
|
||||
|
||||
.badge-break{
|
||||
background:#ffc107;
|
||||
color:#000;
|
||||
}
|
||||
|
||||
.table tbody tr:hover{
|
||||
background:#f8fbff;
|
||||
transition:.3s;
|
||||
}
|
||||
|
||||
.legend span{
|
||||
margin-right:15px;
|
||||
}
|
||||
|
||||
.legend .badge{
|
||||
padding:8px 12px;
|
||||
}
|
||||
|
||||
.today-card{
|
||||
background:white;
|
||||
border-radius:15px;
|
||||
box-shadow:0 10px 25px rgba(0,0,0,.08);
|
||||
padding:25px;
|
||||
/* Top Cards */
|
||||
.top-info-card {
|
||||
background: #ffffff;
|
||||
border: 1px solid #E2E8F0;
|
||||
border-radius: 20px;
|
||||
padding: 26px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.03);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.today-card h5{
|
||||
font-weight:600;
|
||||
.card-title-heading {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
color: #0F172A;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.download-btn{
|
||||
/* Timeline Item for Today */
|
||||
.today-class-item {
|
||||
border-radius: 14px;
|
||||
padding: 14px 18px;
|
||||
margin-bottom: 12px;
|
||||
transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
.today-class-item:hover {
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.today-class-item.theory {
|
||||
background: linear-gradient(135deg, #EFF6FF 0%, #E0E7FF 100%);
|
||||
border: 1px solid #C7D2FE;
|
||||
}
|
||||
|
||||
.today-class-item.practical {
|
||||
background: linear-gradient(135deg, #FEF2F2 0%, #FEE2E2 100%);
|
||||
border: 1px solid #FCA5A5;
|
||||
}
|
||||
|
||||
.today-class-item.workshop {
|
||||
background: linear-gradient(135deg, #FFFBEB 0%, #FEF3C7 100%);
|
||||
border: 1px solid #FDE68A;
|
||||
}
|
||||
|
||||
/* Legend Badges */
|
||||
.legend-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 9px 18px;
|
||||
border-radius: 50px;
|
||||
padding:10px 25px;
|
||||
font-size: 0.84rem;
|
||||
font-weight: 700;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 12px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
@media(max-width:768px){
|
||||
|
||||
.table td,
|
||||
.table th{
|
||||
font-size:13px;
|
||||
min-width:120px;
|
||||
.legend-pill.theory {
|
||||
background: linear-gradient(135deg, #EFF6FF 0%, #DBEAFE 100%);
|
||||
color: #1E40AF;
|
||||
border: 1px solid #BFDBFE;
|
||||
}
|
||||
|
||||
.page-header{
|
||||
padding:25px;
|
||||
.legend-pill.practical {
|
||||
background: linear-gradient(135deg, #FEF2F2 0%, #FEE2E2 100%);
|
||||
color: #991B1B;
|
||||
border: 1px solid #FCA5A5;
|
||||
}
|
||||
|
||||
.legend-pill.workshop {
|
||||
background: linear-gradient(135deg, #FFFBEB 0%, #FEF3C7 100%);
|
||||
color: #92400E;
|
||||
border: 1px solid #FDE68A;
|
||||
}
|
||||
|
||||
.legend-pill.break {
|
||||
background: linear-gradient(135deg, #FEFCE8 0%, #FEF08A 100%);
|
||||
color: #713F12;
|
||||
border: 1px solid #FDE047;
|
||||
}
|
||||
|
||||
/* Timetable Grid Container */
|
||||
.timetable-wrapper {
|
||||
background: #ffffff;
|
||||
border-radius: 20px;
|
||||
border: 1px solid #E2E8F0;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.04);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.table-modern {
|
||||
margin-bottom: 0;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.table-modern thead tr {
|
||||
background: linear-gradient(135deg, #1E233E 0%, #2D355B 100%);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.table-modern thead th {
|
||||
padding: 20px 16px;
|
||||
font-size: 0.88rem;
|
||||
font-weight: 800;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.6px;
|
||||
border: none;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.table-modern thead th.today-header {
|
||||
background: linear-gradient(180deg, rgba(255, 234, 133, 0.22) 0%, rgba(255, 234, 133, 0.1) 100%);
|
||||
color: var(--theme-yellow);
|
||||
border-bottom: 4px solid var(--theme-yellow);
|
||||
}
|
||||
|
||||
.table-modern tbody th.time-column {
|
||||
background: #F8FAFC;
|
||||
color: #334155;
|
||||
font-weight: 700;
|
||||
font-size: 0.85rem;
|
||||
padding: 20px 14px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border-right: 1px solid #E2E8F0;
|
||||
border-bottom: 1px solid #E2E8F0;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.table-modern tbody td {
|
||||
padding: 14px;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
border-right: 1px solid #F1F5F9;
|
||||
border-bottom: 1px solid #E2E8F0;
|
||||
background: #ffffff;
|
||||
transition: background 0.2s ease;
|
||||
min-width: 165px;
|
||||
}
|
||||
|
||||
.table-modern tbody td.today-cell {
|
||||
background: rgba(255, 234, 133, 0.05);
|
||||
}
|
||||
|
||||
.table-modern tbody tr:hover td {
|
||||
background: rgba(248, 250, 252, 0.85);
|
||||
}
|
||||
|
||||
/* Vibrant Class Cards inside Cells */
|
||||
.class-cell-card {
|
||||
border-radius: 14px;
|
||||
padding: 12px 14px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.04);
|
||||
transition: all 0.28s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
cursor: default;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.class-cell-card:hover {
|
||||
transform: translateY(-4px) scale(1.02);
|
||||
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.class-cell-card.theory {
|
||||
background: linear-gradient(135deg, #EFF6FF 0%, #E0E7FF 100%);
|
||||
border: 1px solid #C7D2FE;
|
||||
}
|
||||
|
||||
.class-cell-card.practical {
|
||||
background: linear-gradient(135deg, #FEF2F2 0%, #FEE2E2 100%);
|
||||
border: 1px solid #FCA5A5;
|
||||
}
|
||||
|
||||
.class-cell-card.workshop {
|
||||
background: linear-gradient(135deg, #FFFBEB 0%, #FEF3C7 100%);
|
||||
border: 1px solid #FDE68A;
|
||||
}
|
||||
|
||||
/* Badges inside Class Cell */
|
||||
.type-tag-modern {
|
||||
font-size: 0.72rem;
|
||||
font-weight: 800;
|
||||
padding: 4px 12px;
|
||||
border-radius: 50px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-bottom: 8px;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.type-tag-modern.theory {
|
||||
background: #ffffff;
|
||||
color: #1E40AF;
|
||||
border: 1px solid #BFDBFE;
|
||||
}
|
||||
|
||||
.type-tag-modern.practical {
|
||||
background: #ffffff;
|
||||
color: #991B1B;
|
||||
border: 1px solid #FCA5A5;
|
||||
}
|
||||
|
||||
.type-tag-modern.workshop {
|
||||
background: #ffffff;
|
||||
color: #92400E;
|
||||
border: 1px solid #FDE68A;
|
||||
}
|
||||
|
||||
.subject-title {
|
||||
font-weight: 800;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.35;
|
||||
letter-spacing: -0.2px;
|
||||
}
|
||||
|
||||
.subject-title.theory { color: #1E1B4B; }
|
||||
.subject-title.practical { color: #822424; }
|
||||
.subject-title.workshop { color: #78350F; }
|
||||
|
||||
.empty-cell-badge {
|
||||
color: #94A3B8;
|
||||
font-size: 0.82rem;
|
||||
font-weight: 600;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
/* Lunch Break Row */
|
||||
.lunch-break-row td {
|
||||
background: linear-gradient(90deg, #FEFCE8 0%, #FEF3C7 50%, #FEFCE8 100%) !important;
|
||||
color: #713F12;
|
||||
font-weight: 800;
|
||||
font-size: 0.9rem;
|
||||
padding: 16px !important;
|
||||
border-bottom: 1px solid #FDE047 !important;
|
||||
letter-spacing: 0.4px;
|
||||
}
|
||||
|
||||
/* Print Optimization */
|
||||
@media print {
|
||||
.sidebar, .mobile-header, .btn-print, .title-accent {
|
||||
display: none !important;
|
||||
}
|
||||
.main {
|
||||
margin-left: 0 !important;
|
||||
padding: 0 !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
.portal-content-container {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
.timetable-hero {
|
||||
background: #1E233E !important;
|
||||
color: #ffffff !important;
|
||||
-webkit-print-color-adjust: exact;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container py-4">
|
||||
<div class="portal-content-container">
|
||||
|
||||
<!-- Header -->
|
||||
|
||||
<div class="page-header">
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center flex-wrap">
|
||||
|
||||
<div>
|
||||
|
||||
<h2><i class="fas fa-calendar-alt me-2"></i>My Class Timetable</h2>
|
||||
|
||||
<p class="mb-0">
|
||||
Automobile Engineering Academy Student Portal
|
||||
<!-- Hero Header -->
|
||||
<div class="timetable-hero d-flex align-items-center justify-content-between flex-wrap gap-3">
|
||||
<div class="position-relative" style="z-index: 1;">
|
||||
<div class="d-flex align-items-center gap-2 mb-2">
|
||||
<span class="badge bg-warning bg-opacity-20 text-warning border border-warning border-opacity-20 px-3 py-1.5 rounded-pill fw-semibold" style="font-size: 0.78rem;">
|
||||
<i class="fa-solid fa-calendar-days me-1"></i> Weekly Academic Schedule
|
||||
</span>
|
||||
</div>
|
||||
<h2 class="fw-bold text-white mb-1" style="letter-spacing: -0.5px;">
|
||||
My Class Timetable
|
||||
</h2>
|
||||
<p class="text-white-50 mb-0 fs-6">
|
||||
Automobile Engineering Academy • Student Academic Schedule 2026
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<button class="btn btn-light download-btn" onclick="window.print()">
|
||||
<i class="fas fa-print me-2"></i>Print
|
||||
<button class="btn btn-print shadow-sm" onclick="window.print()">
|
||||
<i class="fa-solid fa-print me-2"></i>Print Timetable
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Top Grid Info Cards -->
|
||||
<div class="row g-3 g-lg-4 mb-4">
|
||||
|
||||
<!-- Today's Schedule Card -->
|
||||
<div class="col-lg-5">
|
||||
<div class="top-info-card">
|
||||
<div class="card-title-heading">
|
||||
<div class="rounded-3 bg-danger bg-opacity-10 text-danger p-2.5 d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
|
||||
<i class="fa-solid fa-clock-rotate-left fs-5"></i>
|
||||
</div>
|
||||
|
||||
<div class="row g-4 mb-4">
|
||||
|
||||
<div class="col-lg-4">
|
||||
|
||||
<div class="today-card">
|
||||
|
||||
<h5 class="mb-3">
|
||||
<i class="fas fa-clock text-primary me-2"></i>
|
||||
Today's Classes
|
||||
</h5>
|
||||
|
||||
<div class="mb-3">
|
||||
|
||||
<strong>08:30 - 10:30</strong><br>
|
||||
|
||||
<span class="badge badge-theory">
|
||||
Theory
|
||||
</span>
|
||||
|
||||
Engine Fundamentals
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
|
||||
<strong>10:45 - 12:30</strong><br>
|
||||
|
||||
<span class="badge badge-workshop">
|
||||
Workshop
|
||||
</span>
|
||||
|
||||
Practical Session
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<strong>01:30 - 03:30</strong><br>
|
||||
|
||||
<span class="badge badge-practical">
|
||||
Practical
|
||||
Today's Schedule
|
||||
<span class="badge bg-danger-subtle text-danger border border-danger-subtle ms-1 fw-bold rounded-pill" style="font-size: 0.72rem;">
|
||||
{{ $todayName ?? 'Today' }}
|
||||
</span>
|
||||
|
||||
Electrical System
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@forelse($todaySchedule ?? [] as $todayItem)
|
||||
@php
|
||||
$typeClass = 'theory';
|
||||
$iconClass = 'fa-book-open';
|
||||
if(strtolower($todayItem->type) == 'practical') {
|
||||
$typeClass = 'practical';
|
||||
$iconClass = 'fa-flask';
|
||||
} elseif(strtolower($todayItem->type) == 'workshop') {
|
||||
$typeClass = 'workshop';
|
||||
$iconClass = 'fa-screwdriver-wrench';
|
||||
}
|
||||
@endphp
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-lg-8">
|
||||
|
||||
<div class="info-card p-4 h-100">
|
||||
|
||||
<h5 class="mb-3">
|
||||
<i class="fas fa-info-circle text-primary me-2"></i>
|
||||
Timetable Legend
|
||||
</h5>
|
||||
|
||||
<div class="legend">
|
||||
|
||||
<span>
|
||||
<span class="badge badge-theory">Theory</span>
|
||||
<div class="today-class-item {{ $typeClass }}">
|
||||
<div class="d-flex align-items-center justify-content-between mb-1">
|
||||
<span class="fw-bold text-dark small"><i class="fa-regular fa-clock me-1 text-secondary"></i> {{ $todayItem->time_slot }}</span>
|
||||
<span class="type-tag-modern {{ $typeClass }} mb-0">
|
||||
<i class="fa-solid {{ $iconClass }}"></i> {{ $todayItem->type }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="subject-title {{ $typeClass }}">{{ $todayItem->subject_name }}</div>
|
||||
</div>
|
||||
@empty
|
||||
<div class="p-4 text-center border rounded-4 bg-light bg-opacity-50">
|
||||
<div class="rounded-circle bg-warning bg-opacity-20 text-warning d-inline-flex align-items-center justify-content-center p-3 mb-2" style="width: 54px; height: 54px;">
|
||||
<i class="fa-solid fa-mug-hot fs-3"></i>
|
||||
</div>
|
||||
<h6 class="fw-bold text-dark mb-1">No classes scheduled for today!</h6>
|
||||
<p class="small text-muted mb-0">Take time to review your course materials or relax.</p>
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span>
|
||||
<span class="badge badge-practical">Practical</span>
|
||||
<!-- Timetable Legend & Guidelines Card -->
|
||||
<div class="col-lg-7">
|
||||
<div class="top-info-card d-flex flex-column justify-content-between">
|
||||
<div>
|
||||
<div class="card-title-heading">
|
||||
<div class="rounded-3 bg-primary bg-opacity-10 text-primary p-2.5 d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
|
||||
<i class="fa-solid fa-sliders fs-5"></i>
|
||||
</div>
|
||||
<span>Timetable Legend & Session Types</span>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<span class="legend-pill theory">
|
||||
<i class="fa-solid fa-book-open"></i> Theory Session
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<span class="badge badge-workshop">Workshop</span>
|
||||
<span class="legend-pill practical">
|
||||
<i class="fa-solid fa-flask"></i> Practical Session
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<span class="badge badge-break">Break</span>
|
||||
<span class="legend-pill workshop">
|
||||
<i class="fa-solid fa-screwdriver-wrench"></i> Workshop Training
|
||||
</span>
|
||||
|
||||
<span class="legend-pill break">
|
||||
<i class="fa-solid fa-utensils"></i> Rest / Lunch Break
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<p class="mb-0 text-muted">
|
||||
Please arrive at least 15 minutes before each class.
|
||||
Attendance is compulsory for all practical sessions.
|
||||
</p>
|
||||
|
||||
<div class="pt-3 border-top border-slate-100 mt-2">
|
||||
<div class="p-3 rounded-4 bg-danger bg-opacity-10 text-danger border border-danger border-opacity-10 d-flex align-items-center gap-3">
|
||||
<div class="rounded-circle bg-danger text-white p-2 d-flex align-items-center justify-content-center flex-shrink-0" style="width: 32px; height: 32px;">
|
||||
<i class="fa-solid fa-exclamation" style="font-size: 14px;"></i>
|
||||
</div>
|
||||
<span class="small fw-semibold">
|
||||
Please arrive at least 15 minutes before each session. 100% attendance is mandatory for practical and workshop modules.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Timetable -->
|
||||
|
||||
<div class="table-card">
|
||||
|
||||
<!-- Main Timetable Grid -->
|
||||
<div class="timetable-wrapper mb-5">
|
||||
<div class="table-responsive">
|
||||
|
||||
<table class="table table-bordered align-middle mb-0">
|
||||
|
||||
<table class="table table-modern align-middle mb-0">
|
||||
<thead>
|
||||
|
||||
<tr>
|
||||
|
||||
<th>Time</th>
|
||||
|
||||
<th>Monday</th>
|
||||
|
||||
<th>Tuesday</th>
|
||||
|
||||
<th>Wednesday</th>
|
||||
|
||||
<th>Thursday</th>
|
||||
|
||||
<th>Friday</th>
|
||||
|
||||
<th style="width: 150px;">
|
||||
<i class="fa-regular fa-clock me-1"></i> Time
|
||||
</th>
|
||||
@foreach($days as $day)
|
||||
@php
|
||||
$isToday = ($todayName ?? '') == $day;
|
||||
@endphp
|
||||
<th class="{{ $isToday ? 'today-header' : '' }}">
|
||||
{{ $day }}
|
||||
@if($isToday)
|
||||
<span class="badge bg-warning text-dark px-2 py-1 rounded-pill ms-1 fw-bold" style="font-size: 0.7rem; box-shadow: 0 2px 8px rgba(255, 234, 133, 0.4);">
|
||||
<i class="fa-solid fa-star me-1"></i>TODAY
|
||||
</span>
|
||||
@endif
|
||||
</th>
|
||||
@endforeach
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
@forelse($timeSlots as $slot)
|
||||
@php
|
||||
$isBreakRow = false;
|
||||
foreach($days as $d) {
|
||||
if(isset($schedule[$slot][$d]) && strtolower($schedule[$slot][$d]->type) == 'break') {
|
||||
$isBreakRow = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@endphp
|
||||
|
||||
@if($isBreakRow)
|
||||
<tr class="lunch-break-row">
|
||||
<th class="time-column">{{ $slot }}</th>
|
||||
<td colspan="5" class="text-center">
|
||||
<i class="fa-solid fa-mug-hot me-2 text-warning"></i> LUNCH BREAK & REST TIME (12:30 PM - 01:30 PM)
|
||||
</td>
|
||||
</tr>
|
||||
@else
|
||||
<tr>
|
||||
|
||||
<th>08:30 - 10:30</th>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-theory">Theory</span><br>
|
||||
Engine Fundamentals
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-practical">Practical</span><br>
|
||||
Engine Lab
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-theory">Theory</span><br>
|
||||
Transmission
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-workshop">Workshop</span><br>
|
||||
Engine Repair
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-theory">Theory</span><br>
|
||||
Vehicle Safety
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
<th>10:45 - 12:30</th>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-workshop">Workshop</span><br>
|
||||
Service Practice
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-theory">Theory</span><br>
|
||||
Electrical
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-practical">Practical</span><br>
|
||||
Diagnostics
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-theory">Theory</span><br>
|
||||
Fuel System
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-workshop">Workshop</span><br>
|
||||
Engine Assembly
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr class="table-warning">
|
||||
|
||||
<th>12:30 - 01:30</th>
|
||||
|
||||
<td colspan="5">
|
||||
🍴 LUNCH BREAK
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
<th>01:30 - 03:30</th>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-practical">Practical</span><br>
|
||||
Electrical System
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-workshop">Workshop</span><br>
|
||||
Welding
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-theory">Theory</span><br>
|
||||
Auto Electronics
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-practical">Practical</span><br>
|
||||
Brake System
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<span class="badge badge-theory">Theory</span><br>
|
||||
Revision
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
<th class="time-column">
|
||||
<div class="d-flex align-items-center justify-content-center gap-1">
|
||||
<i class="fa-regular fa-clock text-muted opacity-75" style="font-size: 0.8rem;"></i>
|
||||
<span>{{ $slot }}</span>
|
||||
</div>
|
||||
</th>
|
||||
@foreach($days as $day)
|
||||
@php
|
||||
$isToday = ($todayName ?? '') == $day;
|
||||
@endphp
|
||||
<td class="{{ $isToday ? 'today-cell' : '' }}">
|
||||
@if(isset($schedule[$slot][$day]))
|
||||
@php
|
||||
$cell = $schedule[$slot][$day];
|
||||
$typeClass = 'theory';
|
||||
$iconClass = 'fa-book-open';
|
||||
|
||||
if(strtolower($cell->type) == 'practical') {
|
||||
$typeClass = 'practical';
|
||||
$iconClass = 'fa-flask';
|
||||
} elseif(strtolower($cell->type) == 'workshop') {
|
||||
$typeClass = 'workshop';
|
||||
$iconClass = 'fa-screwdriver-wrench';
|
||||
}
|
||||
@endphp
|
||||
<div class="class-cell-card {{ $typeClass }}">
|
||||
<div class="type-tag-modern {{ $typeClass }}">
|
||||
<i class="fa-solid {{ $iconClass }}"></i> {{ $cell->type }}
|
||||
</div>
|
||||
<div class="subject-title {{ $typeClass }}">{{ $cell->subject_name }}</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="empty-cell-badge">
|
||||
<i class="fa-solid fa-minus"></i>
|
||||
</div>
|
||||
@endif
|
||||
</td>
|
||||
@endforeach
|
||||
</tr>
|
||||
@endif
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="6" class="text-center py-5 text-muted">
|
||||
<i class="fa-solid fa-calendar-xmark text-secondary mb-2 fs-2 d-block"></i>
|
||||
<span class="fw-semibold">No timetable data available for this week.</span>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
241
routes/web.php
241
routes/web.php
|
|
@ -6,73 +6,198 @@ use App\Http\Controllers\StudentPortalController;
|
|||
use App\Http\Controllers\ContactMsgController;
|
||||
use App\Http\Controllers\FeedbackController;
|
||||
use App\Http\Controllers\studentportalnavController;
|
||||
|
||||
use App\Http\Controllers\Auth\ForgotPasswordController;
|
||||
use App\Http\Controllers\coursesController;
|
||||
use App\Http\Controllers\ApplyController;
|
||||
use App\Http\Controllers\ResultsController;
|
||||
use App\Http\Controllers\TimetableController;
|
||||
use App\Http\Controllers\CoureseAssignController;
|
||||
use App\Http\Controllers\AdminAuthController;
|
||||
use App\Http\Controllers\adminmycoursesController;
|
||||
use App\Http\Controllers\AdminResultsController;
|
||||
use App\Http\Controllers\AdminProfileController;
|
||||
use App\Http\Controllers\AdminTimetableController;
|
||||
use App\Http\Controllers\AdminDashboardController;
|
||||
use App\Http\Controllers\welcomeController;
|
||||
use App\Http\Controllers\DocumentDownloadController;
|
||||
use App\Http\Controllers\MyCoursesController;
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Web Routes
|
||||
| Public Routes & General Pages
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Home Page
|
||||
Route::get('/', function () {
|
||||
return view('welcome');
|
||||
});
|
||||
|
||||
Route::post('/studentlogout', [studentportalnavController::class, 'logout']);
|
||||
|
||||
Route::post('/feedback/store', [FeedbackController::class, 'feedback']) ->middleware('auth') ->name('feedback.store');
|
||||
|
||||
Route::post('/contact-submit', [ContactMsgController::class, 'store'])->name('contact.store');
|
||||
|
||||
Route::put('/profile/update', [AuthController::class, 'update'])->name('profile.update')->middleware('auth');
|
||||
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/profile', [AuthController::class, 'profilview'])->name('profile.view');
|
||||
});
|
||||
|
||||
// Authentication Routes
|
||||
Route::post('/signuppage', [AuthController::class, 'register']);
|
||||
Route::post('/signin', [AuthController::class, 'login']);
|
||||
Route::post('/custom-logout', [AuthController::class, 'logout']);
|
||||
|
||||
|
||||
// --- STUDENT PORTAL SYSTEM ROUTES ---
|
||||
|
||||
|
||||
Route::post('/student-login', [StudentPortalController::class, 'studentlogin'])->name('student.login.submit');
|
||||
// Route::get('/student-login', [StudentPortalController::class, 'studentlogin'])->name('student.login.submit');
|
||||
|
||||
|
||||
|
||||
Route::get('/student-portal', function () {
|
||||
if (!session()->has('student_id')) {
|
||||
return redirect()->back()->with('error', 'Please login first!');
|
||||
}
|
||||
return view('StudentPortal');
|
||||
})->name('student.portal');
|
||||
|
||||
// Route::get('/student-logout', function () {
|
||||
// session()->forget('student_id');
|
||||
// return redirect()->to('/students')->with('success', 'Logged out successfully!');
|
||||
// })->name('student.logout');
|
||||
|
||||
|
||||
Route::view('/apply', 'apply')->name('apply');
|
||||
Route::view('/courses', 'courses')->name('courses');
|
||||
Route::get('/', [welcomeController::class, 'index'])->name('welcome');
|
||||
Route::get('/courses', [coursesController::class, 'index'])->name('courses.index');
|
||||
Route::view('/students', 'students')->name('students');
|
||||
Route::view('/abouts', 'abouts')->name('abouts');
|
||||
Route::view('/contact', 'contacts')->name('contact');
|
||||
|
||||
|
||||
Route::view('/signin', 'signin')->name('signin');
|
||||
Route::get('/login', function () {
|
||||
return redirect()->route('signin')->with('error', 'Please sign in to your account to continue!');
|
||||
})->name('login');
|
||||
Route::view('/signup', 'signup')->name('signup');
|
||||
|
||||
//student protal
|
||||
Route::view('/Dashboard','StudentPortal')->name('Dashboard');
|
||||
Route::view('/mycourse', 'mycourse')->name('mycourse');
|
||||
Route::view('/timetable','timetable')->name('timetable');
|
||||
Route::view('/Assignments','Assignments')->name('Assignments');
|
||||
Route::view('/Studentguidelines','Studentguidelines')->name('Studentguidelines');
|
||||
Route::view('/results','results')->name('results');
|
||||
Route::view('/Feedback&Complain','Feedback&Complain')->name('Feedback&Complain');
|
||||
Route::view('/StudentProfile','StudentProfile')->name('StudentProfile');
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| System Auth & Contact Routes (POST)
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
Route::post('/signuppage', [AuthController::class, 'register']);
|
||||
Route::post('/signin', [AuthController::class, 'login']);
|
||||
Route::post('/custom-logout', [AuthController::class, 'logout']);
|
||||
Route::post('/contact-submit', [ContactMsgController::class, 'store'])->name('contact.store');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reset Routes
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
Route::middleware('guest')->group(function () {
|
||||
Route::get('/password/reset', [ForgotPasswordController::class, 'index'])->name('password.request');
|
||||
Route::post('/resetEmail', [ForgotPasswordController::class, 'resetEmail'])->name('password.email');
|
||||
Route::post('/verify-otp', [ForgotPasswordController::class, 'verifyOtpEmail'])->name('password.verify.otp');
|
||||
Route::post('/update-password', [ForgotPasswordController::class, 'updatePassword'])->name('password.update');
|
||||
});
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Regular Auth Protected Routes
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
Route::middleware(['auth'])->group(function () {
|
||||
Route::get('/apply', [ApplyController::class, 'index'])->name('apply.index');
|
||||
Route::post('/apply', [ApplyController::class, 'store'])->name('apply.store');
|
||||
Route::put('/profile/update', [AuthController::class, 'update'])->name('profile.update');
|
||||
Route::get('/profile', [AuthController::class, 'profilview'])->name('profile.view');
|
||||
});
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| STUDENT PORTAL ROUTES
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
Route::post('/student-login', [StudentPortalController::class, 'studentlogin'])->name('student.login.submit');
|
||||
Route::post('/studentlogout', [StudentPortalController::class, 'studentlogout'])->name('student.logout');
|
||||
|
||||
Route::middleware(['web'])->group(function () {
|
||||
Route::get('/student-portal', [StudentPortalController::class, 'index'])->name('student.portal');
|
||||
|
||||
Route::get('/StudentProfile', [StudentPortalController::class, 'showProfile'])->name('StudentProfile');
|
||||
Route::post('/StudentProfile/update', [StudentPortalController::class, 'updateProfile'])->name('student.profile.update');
|
||||
Route::get('/results', [ResultsController::class, 'index'])->name('results');
|
||||
|
||||
Route::get('/Dashboard', function () {
|
||||
if (!session()->has('student_id') && !session()->has('student_log_id')) {
|
||||
return redirect('/signin')->with('error', 'Please login first!');
|
||||
}
|
||||
return view('StudentPortal');
|
||||
})->name('Dashboard');
|
||||
|
||||
Route::get('/timetable', [TimetableController::class, 'index'])->name('timetable');
|
||||
|
||||
Route::get('/Assignments', function () {
|
||||
if (!session()->has('student_id') && !session()->has('student_log_id')) {
|
||||
return redirect('/signin')->with('error', 'Please login first!');
|
||||
}
|
||||
return view('Assignments');
|
||||
})->name('Assignments');
|
||||
|
||||
Route::get('/Studentguidelines', function () {
|
||||
if (!session()->has('student_id') && !session()->has('student_log_id')) {
|
||||
return redirect('/signin')->with('error', 'Please login first!');
|
||||
}
|
||||
return view('Studentguidelines');
|
||||
})->name('Studentguidelines');
|
||||
|
||||
Route::get('/Feedback&Complain', [FeedbackController::class, 'index'])->name('feedback.index');
|
||||
Route::post('/Feedback&Complain/store', [FeedbackController::class, 'store'])->name('feedback.store');
|
||||
|
||||
Route::get('/mycourse', [CoureseAssignController::class, 'showMyCourse'])->name('mycourse');
|
||||
Route::get('/module/{id}', [CoureseAssignController::class, 'showModule'])->name('module.show');
|
||||
|
||||
Route::get('/mycourse', [MyCoursesController::class, 'showMyCourses'])->name('mycourse');
|
||||
|
||||
|
||||
Route::get('/course/{course_id}/modules', [MyCoursesController::class, 'showModule'])->name('course.modules');
|
||||
|
||||
|
||||
Route::get('/mycourse', [MyCoursesController::class, 'showMyCourses'])->name('mycourse');
|
||||
// Route::get('/module/{course_id}', [MyCoursesController::class, 'showModule'])->name('course.modules');
|
||||
/* Document Downloads */
|
||||
Route::get('/student/download/calendar', [DocumentDownloadController::class, 'downloadAcademicCalendar'])->name('student.download.calendar');
|
||||
Route::get('/student/download/handbook', [DocumentDownloadController::class, 'downloadStudentHandbook'])->name('student.download.handbook');
|
||||
Route::get('/student/download/exam-code', [DocumentDownloadController::class, 'downloadExamCode'])->name('student.download.examcode');
|
||||
Route::get('/student/download/helpdesk', [DocumentDownloadController::class, 'downloadHelpdeskGuide'])->name('student.download.helpdesk');
|
||||
});
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| ADMIN PORTAL ROUTES
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
// Admin Module Routes
|
||||
Route::post('/modules/store', [adminmycoursesController::class, 'storeModule'])->name('modules.store');
|
||||
Route::post('/modules/update/{id}', [adminmycoursesController::class, 'updateModule'])->name('modules.update');
|
||||
Route::delete('/modules/{id}', [adminmycoursesController::class, 'destroyModule'])->name('modules.delete');
|
||||
Route::delete('/courses/{id}', [adminmycoursesController::class, 'destroy'])->name('courses.destroy');
|
||||
|
||||
|
||||
|
||||
Route::get('/admin/login', [AdminAuthController::class, 'showLoginForm'])->name('admin.login');
|
||||
Route::post('/admin/login', [AdminAuthController::class, 'login']);
|
||||
Route::post('/admin/logout', [AdminAuthController::class, 'logout'])->name('admin.logout');
|
||||
|
||||
Route::middleware(['web'])->prefix('admin')->group(function () {
|
||||
|
||||
// Admin Dashboard & Notifications Routes
|
||||
Route::get('/dashboard', [AdminDashboardController::class, 'index'])->name('admin.dashboard');
|
||||
Route::post('/notifications', [AdminDashboardController::class, 'store'])->name('admin.notifications.store');
|
||||
Route::put('/notifications/{id}', [AdminDashboardController::class, 'update'])->name('admin.notifications.update');
|
||||
Route::delete('/notifications/{id}', [AdminDashboardController::class, 'destroy'])->name('admin.notifications.destroy');
|
||||
Route::post('/notifications/read/{id}', [AdminDashboardController::class, 'markAsRead'])->name('admin.notifications.read');
|
||||
|
||||
// Admin Users Management
|
||||
Route::delete('/users/{id}', [AdminDashboardController::class, 'destroyUser'])->name('admin.users.destroy');
|
||||
|
||||
|
||||
Route::post('/portal-logs', [AdminDashboardController::class, 'storePortalLog'])->name('admin.portallogs.store');
|
||||
Route::post('/portal-logs/send/{userId}', [AdminDashboardController::class, 'sendToPortalLog'])->name('admin.portallogs.send');
|
||||
Route::put('/portal-logs/{userId}/pin', [AdminDashboardController::class, 'updatePin'])->name('admin.portallogs.update');
|
||||
Route::delete('/portal-logs/{id}', [AdminDashboardController::class, 'destroyPortalLog'])->name('admin.portallogs.destroy');
|
||||
|
||||
// Admin Courses
|
||||
Route::get('/adminmycourses', [adminmycoursesController::class, 'index'])->name('admin.mycourses');
|
||||
Route::post('/adminmycourses/store', [adminmycoursesController::class, 'store'])->name('admin.courses.store');
|
||||
Route::post('/adminmycourses/update/{id}', [adminmycoursesController::class, 'update'])->name('admin.courses.update');
|
||||
Route::delete('/courses/{id}', [adminmycoursesController::class, 'destroy'])->name('admin.courses.delete');
|
||||
Route::post('/admin/assign-course', [adminmycoursesController::class, 'assignCourse'])
|
||||
->name('assign.course');
|
||||
|
||||
// Admin Timetable Routes
|
||||
Route::get('/timetable', [AdminTimetableController::class, 'index'])->name('admin.timetable');
|
||||
Route::post('/timetable/store', [AdminTimetableController::class, 'store'])->name('admin.timetable.store');
|
||||
Route::put('/timetable/update/{id}', [AdminTimetableController::class, 'update'])->name('admin.timetable.update');
|
||||
Route::delete('/timetable/delete/{id}', [AdminTimetableController::class, 'destroy'])->name('admin.timetable.delete');
|
||||
|
||||
// Admin Results
|
||||
Route::get('/results', [AdminResultsController::class, 'index'])->name('admin.results');
|
||||
Route::post('/results/store', [AdminResultsController::class, 'store'])->name('admin.results.store');
|
||||
Route::put('/results/update/{id}', [AdminResultsController::class, 'update'])->name('admin.results.update');
|
||||
Route::delete('/results/delete/{id}', [AdminResultsController::class, 'destroy'])->name('admin.results.delete');
|
||||
|
||||
// Admin Profile
|
||||
Route::get('/profile', [AdminProfileController::class, 'index'])->name('admin.profile');
|
||||
Route::put('/profile/update', [AdminProfileController::class, 'update'])->name('admin.profile.update');
|
||||
Route::put('/profile/password', [AdminProfileController::class, 'updatePassword'])->name('admin.profile.password');
|
||||
Route::prefix('admin')->name('admin.')->group(function () {
|
||||
|
||||
Route::get('/results', [AdminResultsController::class, 'index'])->name('results.index');
|
||||
|
||||
|
||||
Route::post('/results/import', [AdminResultsController::class, 'import'])->name('results.import');
|
||||
Route::post('/admin/courses/assign', [adminmycoursesController::class, 'assignCourse'])->name('admin.courses.assign');
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue