Compare commits

...

45 Commits

Author SHA1 Message Date
imadhigp e474bc5315 module set 2 2026-08-25 10:19:12 +05:30
imadhigp 8c953d0e46 set my courses module 1 2026-08-24 17:11:18 +05:30
imadhigp 5a9580a568 set mycourses in admin 2026-08-19 09:32:39 +05:30
imadhigp b3423db9d7 set modules 2026-08-17 16:50:30 +05:30
imadhigp 876c896478 set admin result 0817 2026-08-17 09:30:26 +05:30
imadhigp 3207bbddac set admin3 2026-08-15 12:03:52 +05:30
imadhigp 13ecc12812 set admin2 2026-08-15 10:46:55 +05:30
imadhigp d6e1fe2c5d set admin 2026-08-13 17:08:19 +05:30
KaviSaparamadu 97cf0f72d2 ui chngs: 2026-08-10 12:09:35 +05:30
KaviSaparamadu 6f1ef07048 ui chng 2026-08-10 11:04:54 +05:30
KaviSaparamadu 8d357652e7 ui chngs 2026-08-10 10:24:18 +05:30
KaviSaparamadu d7d4d815e3 ui5 2026-08-10 10:08:15 +05:30
KaviSaparamadu 70a97b4019 ui 4 2026-08-10 09:46:55 +05:30
KaviSaparamadu f4e4c45f5f ui3 2026-08-10 09:42:36 +05:30
KaviSaparamadu 86a00cb09e ui 2 2026-08-10 09:20:47 +05:30
KaviSaparamadu d3817ac619 ui 1 2026-08-10 09:08:39 +05:30
imadhigp f5df67c87d welcome top courses view using database 2026-08-08 14:45:08 +05:30
imadhigp a3e71fd181 Merge branch 'setpasswors' into dev 2026-08-08 08:50:28 +05:30
imadhigp c30d5a8d14 set about comment 2026-08-08 08:42:02 +05:30
KaviSaparamadu cb50fbbb19 ui chng 2026-08-07 15:04:46 +05:30
imadhigp e81d20fd50 mission 2026-08-07 14:35:03 +05:30
imadhigp d71dc7ef62 password set 2026-08-07 13:12:26 +05:30
KaviSaparamadu 582c3a7e18 ui 2026-08-07 13:07:19 +05:30
KaviSaparamadu 523179880e ui 2 2026-08-07 12:41:16 +05:30
imadhigp 45fc7e33c9 password set 2026-08-07 12:23:25 +05:30
KaviSaparamadu 5f2abd44b4 ui chngs 2026-08-07 11:57:59 +05:30
KaviSaparamadu ba9b90f6e8 ui1 2026-08-07 11:25:00 +05:30
imadhigp e6b5166782 set code structures 2026-08-07 10:13:29 +05:30
imadhigp db3373002d admin set 3 2026-08-07 09:07:35 +05:30
imadhigp d24235a2b7 admin pages 2026-08-06 16:43:59 +05:30
imadhigp 679e37b780 set mycourese 2026-08-05 12:58:03 +05:30
imadhigp 41934b31fc set result and timetable pages 2026-08-05 10:21:54 +05:30
imadhigp 5d76c711f7 set lms parts 2026-08-04 10:36:33 +05:30
imadhigp 705917497d new chages add 2026-08-03 16:29:58 +05:30
imadhigp 897cd82bc6 set 0731 2026-07-31 09:00:01 +05:30
imadhigp d63e9c0a2b set courese backend 2026-07-28 16:46:11 +05:30
imadhigp fa299bcd7c set forget password backend 2026-07-28 11:56:20 +05:30
imadhigp 309934c18f forget password set 2026-07-27 17:01:28 +05:30
imadhigp a03cfc0f40 ui change new themes 2026-07-23 16:53:17 +05:30
imadhigp 5ca81c9b24 set new themes 0722 2026-07-22 17:06:18 +05:30
imadhigp 021ec03fda set new themes 0721 2026-07-21 16:57:33 +05:30
imadhigp 2e799d798a change themes 0720 2026-07-20 17:02:26 +05:30
imadhigp 4289f1d576 change themes 2026-07-18 17:01:09 +05:30
imadhigp 37cd68f170 change themes blue and red 2026-07-17 17:01:32 +05:30
imadhigp 4f3a79c114 7/16 push home 2026-07-16 19:20:24 +05:30
80 changed files with 14535 additions and 3659 deletions

View File

@ -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!');
}
}

View File

@ -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());
}
}
}

View File

@ -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!');
}
}

View File

@ -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!');
}
}

View File

@ -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!');
}
}

View File

@ -7,6 +7,8 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use App\Mail\WelcomeMail;
class AuthController extends Controller 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) public function register(Request $request)
{ {
$request->validate([ $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); 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.');
} }

View File

@ -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]);
}
}

View File

@ -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',
]);
}
}
}

View File

@ -3,40 +3,75 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Models\Feedback;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
class FeedbackController extends Controller class FeedbackController extends Controller
{ {
// public function feedback(Request $request)
// {
// $request->validate([ public function index(Request $request)
// 'feedback_type' => 'required', {
// 'subject' => 'required|string|max:255', $studentLogId = session('student_log_id') ?? session('student_id');
// 'feedback_text' => 'required|string',
// ]); 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!');
// }
} }

View File

@ -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'));
// }
}

View File

@ -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'));
}
}

View File

@ -4,58 +4,234 @@ namespace App\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use App\Models\StudentPortalLog ;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use App\Models\Notification;
class StudentPortalController extends Controller 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) public function studentlogin(Request $request)
{ {
$request->validate([ $request->validate([
'username' => 'required', 'username' => 'required|string',
'password' => 'required', 'password' => 'required|string',
'pin' => 'required|numeric', 'pin' => 'required|numeric',
]); ]);
$student = DB::table('student_portal_logs') $student = DB::table('student_portal_logs')
->where('email', $request->username) ->where('email', $request->username)
->orWhere('studentid', $request->username)
->first(); ->first();
if ($student && Hash::check($request->password, $student->password) && $student->pin == $request->pin) { 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_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()->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) $student = DB::table('student_details')
// { ->where(function ($query) use ($log_id, $student_code) {
if ($log_id) {
// $log_id = $request->session()->get('student_id'); $query->where('student_portal_log_id', $log_id);
}
if ($student_code) {
// if (!$log_id) {
// return redirect('/')->with('error', 'Please login first!'); if ($log_id) {
// } $query->orWhere('student_id', $student_code);
} else {
$query->where('student_id', $student_code);
// $student = DB::table('student_details') }
// ->where('student_portal_log_id', $log_id) }
// ->first(); })
->first();
// if (!$student) {
// return redirect()->back()->with('error', 'Student details not found!'); if (!$student) {
// } return redirect()->route('student.portal')->with('error', 'Student details not found in database!');
}
// return view('StudentProfile', compact('student'));
// } 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!');
}
} }

View File

@ -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'));
}
}

View File

@ -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');

View File

@ -2,9 +2,60 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\Application;
use Illuminate\Http\Request; 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!');
}
} }

View File

@ -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.');
}
}

View File

@ -2,9 +2,16 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\courses;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class coursesController extends Controller class coursesController extends Controller
{ {
// public function index()
{
$courses = courses::all();
return view('courses', compact('courses'));
}
} }

View File

@ -3,14 +3,18 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class studentportalnavController extends Controller class studentportalnavController extends Controller
{ {
public function logout(Request $request) public function logout(Request $request)
{ {
$request->session()->forget(['student_log_id', 'student_id']);
Auth::logout(); Auth::logout();
$request->session()->invalidate(); $request->session()->invalidate();
$request->session()->regenerateToken(); $request->session()->regenerateToken();
return response()->json([ return response()->json([
'success' => true, 'success' => true,
'message' => 'Logged out successfully' 'message' => 'Logged out successfully'

View File

@ -1,10 +1,20 @@
<?php <?php
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\courses;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class welcomeController extends Controller class welcomeController extends Controller
{ {
//
public function index()
{
$courses = courses::where('status', 'active')
->latest()
->take(3)
->get();
return view('welcome', compact('courses'));
}
} }

View File

@ -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'],
]);
}
}

56
app/Mail/OtpEmail.php Normal file
View File

@ -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 [];
}
}

57
app/Mail/WelcomeMail.php Normal file
View File

@ -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 [];
}
}

View File

@ -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);
}
}

View File

@ -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');
}
}

View File

@ -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',
];
}

25
app/Models/Result.php Normal file
View File

@ -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',
];
}

View File

@ -2,24 +2,37 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class StudentPortalLog extends Model class StudentPortalLog extends Model
{ {
use HasFactory;
protected $table = 'student_portal_logs'; protected $table = 'student_portal_logs';
protected $fillable = [ protected $fillable = [
'user_id',
'first_name',
'last_name',
'email', 'email',
'phone',
'studentid', 'studentid',
'password', 'password',
'pin', 'pin',
'status', 'status',
]; ];
protected $hidden = [ protected $hidden = [
'password', 'password',
'pin', 'pin',
]; ];
/**
* Get the user associated with this portal log.
*/
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
} }

22
app/Models/Timetable.php Normal file
View File

@ -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',
];
}

View File

@ -24,6 +24,7 @@ class User extends Authenticatable
'email', 'email',
'phone', 'phone',
'password', 'password',
'email_otp',
]; ];
/** /**

19
app/Models/adminlogin.php Normal file
View File

@ -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',
];
}

View File

@ -0,0 +1,10 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class courseModules extends Model
{
//
}

View File

@ -2,9 +2,39 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class courses extends 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'
);
}
} }

33
app/Models/modules.php Normal file
View File

@ -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);
}
}

View File

@ -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
{
}
}

View File

@ -3,6 +3,8 @@
namespace App\Providers; namespace App\Providers;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use App\Models\User;
use App\Observers\UserObserver;
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
{ {
@ -19,6 +21,6 @@ class AppServiceProvider extends ServiceProvider
*/ */
public function boot(): void public function boot(): void
{ {
// User::observe(UserObserver::class);
} }
} }

View File

@ -7,8 +7,10 @@
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": "^8.2", "php": "^8.2",
"barryvdh/laravel-dompdf": "^3.1",
"laravel/framework": "^12.0", "laravel/framework": "^12.0",
"laravel/tinker": "^2.10.1" "laravel/tinker": "^2.10.1",
"maatwebsite/excel": "^3.1"
}, },
"require-dev": { "require-dev": {
"fakerphp/faker": "^1.23", "fakerphp/faker": "^1.23",

1112
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -11,12 +11,18 @@ return new class extends Migration
*/ */
public function up(): void public function up(): void
{ {
Schema::table('student_portal_logs', function (Blueprint $table) { Schema::create('student_portal_logs', function (Blueprint $table) {
$table->foreignId('user_id') $table->id();
->nullable() $table->foreignId('user_id')->nullable()->constrained('users')->onDelete('cascade');
->after('email') $table->string('first_name')->nullable();
->constrained('users') $table->string('last_name')->nullable();
->onDelete('cascade'); $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 public function down(): void
{ {
Schema::table('student_portal_logs', function (Blueprint $table) { Schema::dropIfExists('student_portal_logs');
$table->dropForeign(['user_id']);
$table->dropColumn('user_id');
});
} }
}; };

View File

@ -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');
});
}
};

View File

@ -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');
}
};

View File

@ -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');
}
};

View File

@ -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');
}
};

View File

@ -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');
}
};

View File

@ -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');
}
};

View File

@ -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');
}
};

View File

@ -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');
});
}
};

View File

@ -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');
}
};

View File

@ -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

View File

@ -4,102 +4,126 @@
@section('content') @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> <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 { body {
background:#f6f7fb; font-family: 'Poppins', sans-serif;
background: var(--bg-light);
} }
/* Header */
.feedback-header { .feedback-header {
background:linear-gradient(135deg,#5E244E,#4a1c3e); background: linear-gradient(135deg, #2B293F 0%, #94A6F959 100%) !important;
color:white; color: var(--white);
padding:40px; padding: 35px 30px;
border-radius:20px; border-radius: 16px;
margin-bottom:35px; margin-bottom: 30px;
box-shadow:0 15px 35px rgba(0,0,0,.12); 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 { .feedback-card {
background:#fff; background: var(--white);
border-radius:20px; border: 1px solid #e2e8f0;
border:none; border-radius: 16px;
padding: 30px; padding: 30px;
box-shadow:0 10px 30px rgba(0,0,0,.08); box-shadow: 0 4px 15px rgba(0, 0, 0, .04);
height: 100%; height: 100%;
} }
.card-title { .card-title {
color:#5E244E; color: var(--theme-navy);
font-weight: 700; font-weight: 700;
margin-bottom: 25px; margin-bottom: 25px;
} }
.card-title i { .card-title i {
color:#d4af37; color: var(--theme-red);
margin-right: 8px; margin-right: 8px;
} }
/* Inputs */ .form-label {
.form-control, font-weight: 600;
.form-select{ color: var(--theme-navy);
border-radius:15px; font-size: 14px;
padding:12px;
border:1px solid #ddd;
} }
.form-control:focus, .form-control, .form-select {
.form-select:focus{ border-radius: 10px;
border-color:#744a68; padding: 12px 15px;
box-shadow:0 0 0 .2rem rgba(94,36,78,.15); border: 1px solid #cbd5e1;
font-size: 14px;
} }
/* Button */
.submit-btn { .submit-btn {
background:#5E244E; background: var(--theme-red) !important;
color:white; color: var(--white) !important;
border: none; border: none;
border-radius:50px; border-radius: 8px;
padding: 12px 30px; padding: 12px 30px;
font-weight: 600; font-weight: 600;
transition: all 0.2s ease;
width: 100%;
} }
.submit-btn:hover { .submit-btn:hover {
background:#4a1c3e; background: var(--theme-red-hover) !important;
color:#fff; color: var(--white) !important;
} }
/* History */
.history-card { .history-card {
margin-top: 35px; margin-top: 35px;
background:white; background: var(--white);
border-radius:20px; border: 1px solid #e2e8f0;
border-radius: 16px;
overflow: hidden; overflow: hidden;
box-shadow:0 10px 30px rgba(0,0,0,.08); box-shadow: 0 4px 15px rgba(0, 0, 0, .04);
} }
.history-head { .history-head {
background:#5E244E; background: var(--theme-navy);
color:white; color: var(--white);
padding: 18px 25px; 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 { .badge-status {
padding:7px 15px; padding: 6px 14px;
border-radius:50px; border-radius: 30px;
font-size:13px; font-size: 12px;
font-weight: 600;
display: inline-block;
} }
.pending { .pending {
background:#fff3cd; background: rgba(255, 234, 133, 0.4);
color: #856404; color: #856404;
} }
@ -113,89 +137,28 @@ body{
<!-- Header --> <!-- Header -->
<div class="feedback-header"> <div class="feedback-header">
<h2><i class="fas fa-comments"></i> Feedback & Complaint</h2> <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 <p>Share your suggestions, feedback, or complaints with the Automobile Engineering Academy management team.</p>
Automobile Engineering Academy management team.</p>
</div> </div>
<div class="row g-4"> <!-- Alert Messages -->
<!-- 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
@if(session('success')) @if(session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert"> <div class="alert alert-success alert-dismissible fade show rounded-3 mb-4" role="alert">
{{ session('success') }} <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> </div>
@endif @endif
@if ($errors->any()) @if ($errors->any())
<div class="alert alert-danger"> <div class="alert alert-danger rounded-3 mb-4">
<ul class="mb-0"> <ul class="mb-0 ps-3">
@foreach ($errors->all() as $error) @foreach ($errors->all() as $error)
<li>{{ $error }}</li> <li>{{ $error }}</li>
@endforeach @endforeach
@ -203,6 +166,15 @@ body{
</div> </div>
@endif @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"> <div class="mb-3">
<label class="form-label"> Feedback Type </label> <label class="form-label"> Feedback Type </label>
<select class="form-select" id="feedbackType" name="feedback_type" required> <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> <input type="text" class="form-control" id="feedbackSubject" name="subject" value="{{ old('subject') }}" placeholder="Enter subject" required>
</div> </div>
<div class="mb-3"> <div class="mb-4">
<label class="form-label">Your Feedback </label> <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> <textarea class="form-control" id="feedbackText" name="feedback_text" rows="5" placeholder="Write your feedback" required>{{ old('feedback_text') }}</textarea>
</div> </div>
<button type="submit" class="submit-btn"> <button type="submit" class="submit-btn shadow-sm">
<i class="fas fa-paper-plane"></i> Submit Feedback <i class="fas fa-paper-plane me-2"></i>Submit Feedback
</button> </button>
</form> </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-card">
<div class="history-head"> <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>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover mb-0"> <table class="table table-hover align-middle mb-0">
<thead> <thead>
<tr> <tr>
<th> Type </th> <th> Type </th>
@ -247,18 +259,31 @@ body{
</thead> </thead>
<tbody id="historyTableBody"> <tbody id="historyTableBody">
@forelse ($feedbacks as $item)
<tr> <tr>
<td>Feedback</td> <td>
<td>Workshop Equipment </td> <span class="fw-semibold" style="color: var(--theme-navy);">
<td>10 July 2026</td> {{ $item->feedback_type }}
<td><span class="badge-status resolved"> Resolved</span></td> </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> </tr>
@empty
<tr> <tr>
<td>Complaint</td> <td colspan="4" class="text-center py-4 text-muted">
<td>Class Schedule Issue </td> <i class="fas fa-inbox fa-2x mb-2 d-block"></i>
<td>05 July 2026 </td> No feedback or complaints submitted yet.
<td><span class="badge-status pending"> Pending </span></td> </td>
</tr> </tr>
@endforelse
</tbody> </tbody>
</table> </table>
</div> </div>
@ -266,6 +291,4 @@ body{
</div> </div>
@endsection @endsection

View File

@ -1,310 +1,554 @@
@extends('layouts.studentportalnav') @extends('layouts.studentportalnav')
@section('title','Dashboard') @section('title', 'Student Dashboard')
@section('content') @section('content')
<style> <style>
:root { :root {
--primary:#5E244E; --theme-navy: #1E233E;
--secondary:#8B3A74; --theme-navy-dark: #15182C;
--light:#f5f6fb; --theme-red: #822424;
--dark:#2d2d2d; --theme-red-hover: #df2c3e;
--theme-yellow: #FFEA85;
--theme-bg: #F4F6F9;
--text-dark: #1E293B;
} }
body{ /* Welcome Banner */
background:var(--light); .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 */ .welcome-banner::before {
.dashboard-header{ content: '';
display:flex; position: absolute;
justify-content:space-between; top: -50%;
align-items:center; right: -10%;
margin-bottom:30px; width: 350px;
} height: 350px;
background: radial-gradient(circle, rgba(255, 234, 133, 0.12) 0%, rgba(255, 234, 133, 0) 70%);
.dashboard-header h2{
font-weight:700;
color:var(--dark);
}
.dashboard-header p{
color:#777;
margin:0;
}
.avatar{
width:55px;
height:55px;
border-radius: 50%; border-radius: 50%;
background:var(--primary); pointer-events: none;
color:#fff; }
.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; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-weight:bold; font-weight: 800;
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-size: 22px; font-size: 22px;
margin-bottom:20px; box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);
} }
.stat-card h3{ /* Stat Cards Modern */
font-weight:700; .stat-card-modern {
margin-bottom:5px; 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{ .stat-card-modern:hover {
color:#777; transform: translateY(-5px);
margin:0; 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-size: 24px;
font-weight:bold; margin-bottom: 20px;
margin:40px 0 20px; background: rgba(130, 36, 36, 0.08);
color: var(--theme-red);
transition: all 0.3s ease;
} }
.service-card{ .service-card-modern:hover .service-icon-box {
background:#fff; background: var(--theme-red);
border-radius:15px; color: #ffffff;
padding:30px; transform: scale(1.08);
text-align:center; box-shadow: 0 6px 16px rgba(130, 36, 36, 0.3);
transition:.3s; }
box-shadow:0 8px 20px rgba(0,0,0,.08);
.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%; height: 100%;
} }
.service-card:hover{ .doc-card:hover {
transform:translateY(-8px); transform: translateY(-5px);
box-shadow: 0 12px 24px rgba(0,0,0,0.08);
border-color: #CBD5E1;
} }
.service-card i{ .doc-icon-badge {
font-size:45px; width: 52px;
color:var(--primary); height: 52px;
margin-bottom:20px; border-radius: 14px;
} background: #FEF2F2;
color: #DC2626;
.service-card h5{ display: flex;
font-weight:700; align-items: center;
} justify-content: center;
font-size: 24px;
.service-card p{ margin: 0 auto 16px;
color:#777;
font-size:14px;
} }
</style> </style>
<div class="container-fluid"> <div class="portal-content-container">
<div class="dashboard-header">
<!-- 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> <div>
<h2>Welcome Back, student <div class="d-flex align-items-center gap-2 mb-2 flex-wrap">
<p>Manage your academic activities from your dashboard.</p> <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>
<!-- <div class="avatar"> @if(Auth::check())
S <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> --> <div class="avatar-circle">
{{ strtoupper(substr(Auth::user()->first_name, 0, 1)) }}
</div> </div>
<div class="text-white d-none d-sm-block">
<!-- Statistics --> <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 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> </div>
</div>
<h3>6</h3> @endif
<p>Enrolled Courses</p>
</div> </div>
</div> </div>
<div class="col-lg-3 col-md-6"> <!-- Key Performance Metrics (Stat Cards) -->
<div class="stat-card"> <div class="row g-3 g-lg-4 mb-4">
<div class="stat-icon" style="background:#0d9488;"> <div class="col-xl-3 col-md-6">
<i class="fa-solid fa-file-lines"></i> <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> </div>
<h3>3</h3>
<p>Assignments</p>
</div> </div>
</div> </div>
<div class="col-lg-3 col-md-6"> <div class="col-xl-3 col-md-6">
<div class="stat-card"> <div class="stat-card-modern">
<div class="d-flex align-items-center justify-content-between mb-3">
<div class="stat-icon" style="background:#d97706;"> <div class="stat-icon-wrapper" style="background: linear-gradient(135deg, #10B981 0%, #047857 100%);">
<i class="fa-solid fa-chart-column"></i> <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> </div>
<h3>78%</h3>
<p>Average Result</p>
</div> </div>
</div> </div>
<div class="col-lg-3 col-md-6"> <div class="col-xl-3 col-md-6">
<div class="stat-card"> <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> <i class="fa-solid fa-bell"></i>
</div> </div>
<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;">
<h3>2</h3> <i class="fa-solid fa-bullhorn me-1"></i> Upcoming
<p>Exam Notices</p> </span>
</div>
<div>
<div class="stat-number">2</div>
<div class="stat-label">Exam Notices</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<!-- Services -->
<div class="section-title"> <div class="col-lg-5" id="notifications-section" style="width: 100%;">
Student Services <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>
<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"> <div class="col-lg-4 col-md-6">
<a href="/mycourse" class="text-decoration-none" style="color:#5E244E"> <a href="/mycourse" class="service-card-modern">
<div>
<div class="service-card"> <div class="service-icon-box">
<i class="fa-solid fa-book-bookmark"></i>
<i class="fa-solid fa-book"></i> </div>
<h5>My Courses</h5> <h5>My Courses</h5>
<p>Access all registered learning modules, video lectures, and syllabus materials.</p>
<p>Access all learning materials and course content.</p> </div>
<div class="action-link">
Explore Courses <i class="fa-solid fa-arrow-right"></i>
</div> </div>
</a> </a>
</div> </div>
<div class="col-lg-4 col-md-6"> <div class="col-lg-4 col-md-6">
<a href="/timetable" class="text-decoration-none" style="color:#5E244E"> <a href="/timetable" class="service-card-modern">
<div>
<div class="service-card"> <div class="service-icon-box">
<i class="fa-solid fa-calendar-days"></i> <i class="fa-solid fa-calendar-days"></i>
</div>
<h5>Class Timetable</h5> <h5>Class Timetable</h5>
<p>Check your weekly lecture schedules, classroom locations, and timing updates.</p>
<p>View your weekly lecture timetable.</p> </div>
<div class="action-link">
View Schedule <i class="fa-solid fa-arrow-right"></i>
</div> </div>
</a> </a>
</div> </div>
<div class="col-lg-4 col-md-6"> <div class="col-lg-4 col-md-6">
<a href="/Assignments" class="text-decoration-none" style="color:#5E244E"> <a href="/results" class="service-card-modern">
<div>
<div class="service-card"> <div class="service-icon-box">
<i class="fa-solid fa-award"></i>
<i class="fa-solid fa-file-lines"></i>
<h5>Assignments</h5>
<p>Submit and manage assignments.</p>
</div> </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> <h5>Exam Results</h5>
<p>Review semester examination grades, transcript records, and academic progress.</p>
<p>Check semester examination results.</p> </div>
<div class="action-link">
View Marks <i class="fa-solid fa-arrow-right"></i>
</div> </div>
</a> </a>
</div> </div>
<div class="col-lg-4 col-md-6"> <div class="col-lg-4 col-md-6">
<a href="/Feedback&Complain" class="text-decoration-none"style="color:#5E244E"> <a href="/Studentguidelines" class="service-card-modern">
<div>
<div class="service-card"> <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> <i class="fa-solid fa-comments"></i>
<h5>Feedback & Complaint</h5>
<p>Send feedback and contact administration.</p>
</div> </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> </a>
</div> </div>
<div class="col-lg-4 col-md-6"> <div class="col-lg-4 col-md-6">
<a href="/StudentProfile" class="service-card-modern">
<a href="/StudentProfile" class="text-decoration-none"style="color:#5E244E"> <div>
<div class="service-icon-box">
<div class="service-card"> <i class="fa-solid fa-id-card"></i>
</div>
<i class="fa-solid fa-user"></i> <h5>Student Profile</h5>
<p>View and update your personal contact details, credentials, and security PIN.</p>
<!-- <a href="{{ route('StudentProfile') }}" class="text-decoration-none"style="color:#5E244E"> </div>
<div class="service-card"> <div class="action-link">
<i class="fas fa-user"></i> Profile Manage Profile <i class="fa-solid fa-arrow-right"></i>
</a> -->
<h5>Student Profile</h5>
<p>Update your personal information.</p>
</div> </div>
</a> </a>
</div> </div>
</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> </div>

File diff suppressed because it is too large Load Diff

View File

@ -4,23 +4,42 @@
@section('content') @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> <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 { body {
background:#f6f7fb; font-family: 'Poppins', sans-serif;
background: var(--bg-light);
} }
/*========================== /*==========================
Hero Hero Section
===========================*/ ===========================*/
.guideline-hero { .guideline-hero {
background:linear-gradient(135deg,#5E244E,#4a1c3e); background: linear-gradient(135deg, #2B293F 0%, #94A6F959 100%) !important;
border-radius:20px; border-radius: 16px;
padding:45px; padding: 35px 30px;
color:#fff; color: var(--white);
margin-bottom:35px; margin-bottom: 30px;
box-shadow:0 18px 40px rgba(0,0,0,.12); box-shadow: 0 8px 25px rgba(31, 37, 65, 0.15);
border-left: 5px solid var(--theme-red);
} }
.guideline-hero h2 { .guideline-hero h2 {
@ -29,444 +48,304 @@ Hero
} }
.guideline-hero p { .guideline-hero p {
color:#ececec; color: rgba(255, 255, 255, 0.85);
margin-bottom: 0; margin-bottom: 0;
font-size: 15px; font-size: 15px;
} }
/*========================== /*==========================
Cards Guide Cards
===========================*/ ===========================*/
.guide-card { .guide-card {
background: var(--white);
background:#fff; border: 1px solid #e2e8f0;
border:none; border-radius: 16px;
border-radius:20px; box-shadow: 0 4px 15px rgba(0, 0, 0, .04);
box-shadow:0 10px 30px rgba(0,0,0,.08); transition: all 0.3s ease;
transition:.3s;
overflow: hidden; overflow: hidden;
height: 100%; height: 100%;
} }
.guide-card:hover { .guide-card:hover {
transform: translateY(-4px);
transform:translateY(-6px); border-color: var(--theme-navy);
box-shadow: 0 10px 22px rgba(0, 0, 0, 0.08);
} }
.card-head { .card-head {
background: #753636;
background:#5E244E; color: var(--white);
color:#fff;
padding: 18px 22px; padding: 18px 22px;
} }
.card-head h5 { .card-head h5 {
margin: 0; margin: 0;
font-weight: 600; font-weight: 600;
} }
.card-head i { .card-head i {
color: var(--theme-yellow);
color:#d4af37;
margin-right: 10px; margin-right: 10px;
} }
.card-body { .card-body {
padding: 22px; padding: 22px;
} }
.card-body ul { .card-body ul {
padding-left: 20px; padding-left: 20px;
margin-bottom: 0;
} }
.card-body li { .card-body li {
margin-bottom: 10px; margin-bottom: 10px;
color:#555; color: #475569;
}
.card-body li:last-child {
margin-bottom: 0;
} }
/*========================== /*==========================
Alert Notice Alert Box
===========================*/ ===========================*/
.notice { .notice {
background: rgba(255, 234, 133, 0.2);
background:#fff7e4; border-left: 5px solid var(--theme-red);
border-left:6px solid #d4af37;
border-radius: 16px; border-radius: 16px;
padding: 22px; padding: 22px;
margin-top: 35px; 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 { .notice h5 {
color: var(--theme-navy);
color:#5E244E;
font-weight: 700; font-weight: 700;
} }
.notice p { .notice p {
margin-bottom: 0; margin-bottom: 0;
color:#555; color: #475569;
} }
/*========================== /*==========================
Contact Contact Box
===========================*/ ===========================*/
.contact-card { .contact-card {
margin-top: 30px;
margin-top:35px; border-radius: 16px;
border-radius:20px; background: linear-gradient(135deg, #2B293F 0%, #94A6F959 100%) !important;
background:#4a1c3e; color: var(--white);
color:#fff;
padding: 35px; 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 { .contact-card h4 {
color: var(--theme-yellow);
color:#d4af37;
font-weight: 700; font-weight: 700;
} }
.contact-item { .contact-item {
margin-top: 18px; margin-top: 18px;
font-size: 15px; font-size: 15px;
} }
.contact-item i { .contact-item i {
color: var(--theme-yellow);
color:#d4af37;
width: 28px; width: 28px;
} }
@media(max-width:768px) {
.guideline-hero, .contact-card {
padding: 25px;
}
}
</style> </style>
<div class="container py-4"> <div class="container py-4">
<!-- Hero --> <!-- Hero -->
<div class="guideline-hero"> <div class="guideline-hero">
<h2> <h2>
<i class="fas fa-book-open"></i> <i class="fas fa-book-open me-2" style="color: var(--theme-yellow);"></i>
Student Guidelines Student Guidelines
</h2> </h2>
<p> <p>
Welcome to the Automobile Engineering Academy. These guidelines are Welcome to the Automobile Engineering Academy. These guidelines are
designed to help every student maintain professionalism, safety, designed to help every student maintain professionalism, safety,
discipline, and academic excellence throughout the training programme. discipline, and academic excellence throughout the training programme.
</p> </p>
</div> </div>
<!-- Guidelines Cards -->
<div class="row g-4"> <div class="row g-4">
<!-- Classroom --> <!-- Classroom -->
<div class="col-lg-6"> <div class="col-lg-6">
<div class="guide-card"> <div class="guide-card">
<div class="card-head"> <div class="card-head">
<h5> <h5>
<i class="fas fa-chalkboard-teacher"></i> <i class="fas fa-chalkboard-teacher"></i>
Classroom Rules Classroom Rules
</h5> </h5>
</div> </div>
<div class="card-body"> <div class="card-body">
<ul> <ul>
<li>Attend every class on time.</li> <li>Attend every class on time.</li>
<li>Maintain discipline and respect lecturers.</li> <li>Maintain discipline and respect lecturers.</li>
<li>Switch mobile phones to silent mode.</li> <li>Switch mobile phones to silent mode.</li>
<li>Complete all assignments before deadlines.</li> <li>Complete all assignments before deadlines.</li>
<li>Keep classrooms clean and organized.</li> <li>Keep classrooms clean and organized.</li>
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>
<!-- Workshop --> <!-- Workshop -->
<div class="col-lg-6"> <div class="col-lg-6">
<div class="guide-card"> <div class="guide-card">
<div class="card-head"> <div class="card-head">
<h5> <h5>
<i class="fas fa-tools"></i> <i class="fas fa-tools"></i>
Workshop Safety Workshop Safety
</h5> </h5>
</div> </div>
<div class="card-body"> <div class="card-body">
<ul> <ul>
<li>Wear PPE before entering workshops.</li> <li>Wear PPE before entering workshops.</li>
<li>Follow instructor safety instructions.</li> <li>Follow instructor safety instructions.</li>
<li>Never operate equipment without permission.</li> <li>Never operate equipment without permission.</li>
<li>Report damaged tools immediately.</li> <li>Report damaged tools immediately.</li>
<li>Keep workstations clean after practical sessions.</li> <li>Keep workstations clean after practical sessions.</li>
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>
<!-- Attendance --> <!-- Attendance -->
<div class="col-lg-6"> <div class="col-lg-6">
<div class="guide-card"> <div class="guide-card">
<div class="card-head"> <div class="card-head">
<h5> <h5>
<i class="fas fa-user-check"></i> <i class="fas fa-user-check"></i>
Attendance Policy Attendance Policy
</h5> </h5>
</div> </div>
<div class="card-body"> <div class="card-body">
<ul> <ul>
<li>Minimum attendance requirement is 80%.</li> <li>Minimum attendance requirement is 80%.</li>
<li>Medical leave must be supported by documents.</li> <li>Medical leave must be supported by documents.</li>
<li>Repeated absence may affect examinations.</li> <li>Repeated absence may affect examinations.</li>
<li>Late arrivals will be recorded.</li> <li>Late arrivals will be recorded.</li>
<li>Inform the administration if absent.</li> <li>Inform the administration if absent.</li>
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>
<!-- Dress --> <!-- Dress -->
<div class="col-lg-6"> <div class="col-lg-6">
<div class="guide-card"> <div class="guide-card">
<div class="card-head"> <div class="card-head">
<h5> <h5>
<i class="fas fa-user-tie"></i> <i class="fas fa-user-tie"></i>
Uniform & PPE Uniform & PPE
</h5> </h5>
</div> </div>
<div class="card-body"> <div class="card-body">
<ul> <ul>
<li>Wear academy uniform during lectures.</li> <li>Wear academy uniform during lectures.</li>
<li>Safety shoes are compulsory.</li> <li>Safety shoes are compulsory.</li>
<li>Use gloves and safety glasses.</li> <li>Use gloves and safety glasses.</li>
<li>Long hair must be tied properly.</li> <li>Long hair must be tied properly.</li>
<li>ID card must be visible at all times.</li> <li>ID card must be visible at all times.</li>
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>
<!-- Assessment --> <!-- Assessment -->
<div class="col-lg-6"> <div class="col-lg-6">
<div class="guide-card"> <div class="guide-card">
<div class="card-head"> <div class="card-head">
<h5> <h5>
<i class="fas fa-file-alt"></i> <i class="fas fa-file-alt"></i>
Assessment Rules Assessment Rules
</h5> </h5>
</div> </div>
<div class="card-body"> <div class="card-body">
<ul> <ul>
<li>Submit assignments before due dates.</li> <li>Submit assignments before due dates.</li>
<li>No plagiarism is permitted.</li> <li>No plagiarism is permitted.</li>
<li>Bring required materials for practical tests.</li> <li>Bring required materials for practical tests.</li>
<li>Follow examination regulations.</li> <li>Follow examination regulations.</li>
<li>Maintain academic honesty.</li> <li>Maintain academic honesty.</li>
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>
<!-- Conduct --> <!-- Conduct -->
<div class="col-lg-6"> <div class="col-lg-6">
<div class="guide-card"> <div class="guide-card">
<div class="card-head"> <div class="card-head">
<h5> <h5>
<i class="fas fa-handshake"></i> <i class="fas fa-handshake"></i>
Student Conduct Student Conduct
</h5> </h5>
</div> </div>
<div class="card-body"> <div class="card-body">
<ul> <ul>
<li>Respect staff and fellow students.</li> <li>Respect staff and fellow students.</li>
<li>Protect academy property.</li> <li>Protect academy property.</li>
<li>Do not smoke inside the campus.</li> <li>Do not smoke inside the campus.</li>
<li>Avoid discrimination and harassment.</li> <li>Avoid discrimination and harassment.</li>
<li>Represent the academy professionally.</li> <li>Represent the academy professionally.</li>
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- Notice --> <!-- Notice -->
<div class="notice"> <div class="notice">
<h5> <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 Important Notice
</h5> </h5>
<p> <p>
Students who fail to follow academy regulations may face disciplinary Students who fail to follow academy regulations may face disciplinary
action according to the Automobile Engineering Academy Student Policy. action according to the Automobile Engineering Academy Student Policy.
</p> </p>
</div> </div>
<!-- Contact --> <!-- Contact -->
<div class="contact-card"> <div class="contact-card">
<h4> <h4>
<i class="fas fa-headset me-2"></i>
<i class="fas fa-headset"></i>
Student Support Student Support
</h4> </h4>
<p class="mt-3 text-white-50">
<p class="mt-3">
If you have any questions regarding academic regulations, If you have any questions regarding academic regulations,
attendance, workshop safety, or student services, please contact attendance, workshop safety, or student services, please contact
the Student Affairs Office. the Student Affairs Office.
</p> </p>
<div class="contact-item"> <div class="contact-item">
<i class="fas fa-envelope"></i> <i class="fas fa-envelope"></i>
support@academy.lk support@academy.lk
</div> </div>
<div class="contact-item"> <div class="contact-item">
<i class="fas fa-phone"></i> <i class="fas fa-phone"></i>
+94 11 234 5678 +94 11 234 5678
</div> </div>
<div class="contact-item"> <div class="contact-item">
<i class="fas fa-map-marker-alt"></i> <i class="fas fa-map-marker-alt"></i>
Automobile Engineering Academy Automobile Engineering Academy
</div> </div>
</div> </div>
</div> </div>

View File

@ -6,186 +6,358 @@
<style> <style>
:root { :root {
--primary:#5E244E; --primary: #3E51B8; /* Tech Blue */
--secondary:#8B3A74; --primary-light: #0a67df; /* Vibrant Electric Blue */
--light:#f8f4f7; --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 { .hero-about {
min-height:60vh; position: relative;
background: min-height: 48vh;
linear-gradient(rgba(0,0,0,.7),rgba(0,0,0,.7)), 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.pexels.com/photos/1595385/pexels-photo-1595385.jpeg'); url('https://images.unsplash.com/photo-1617814076367-b759c7d7e738?auto=format&fit=crop&w=1600&q=80');
background-size: cover; background-size: cover;
background-position: center; background-position: center;
background-attachment: fixed;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
text-align: center; text-align: center;
color:#fff; color: #ffffff;
padding: 70px 20px;
overflow: hidden;
} }
.section-title{ .hero-badge {
text-align:center; display: inline-flex;
margin-bottom:40px; 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 { .hero-about h1 {
background:#fff; 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; border-radius: 20px;
padding:35px 25px; padding: 20px 16px;
box-shadow:0 10px 30px rgba(0,0,0,.05); text-align: center;
transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1); box-shadow: 0 10px 28px rgba(15, 23, 42, 0.06);
border: 1px solid #efeff4; 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 { .about-box:hover {
transform: translateY(-10px) scale(1.02); transform: translateY(-8px);
box-shadow: 0 20px 40px rgba(94, 36, 78, 0.1); box-shadow: 0 20px 45px -10px rgba(62, 81, 184, 0.14);
border-color: var(--primary); border-color: rgba(62, 81, 184, 0.3);
} }
.icon-circle { .icon-circle {
width:75px; width: 64px;
height:75px; height: 64px;
background:var(--primary); background: linear-gradient(135deg, rgba(62, 81, 184, 0.1) 0%, rgba(10, 103, 223, 0.06) 100%);
color:#fff; color: var(--primary);
border-radius:50%; border-radius: 20px;
border: 1px solid rgba(62, 81, 184, 0.2);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-size:28px; font-size: 26px;
margin:auto; margin: 0 auto 20px;
transition: all 0.4s ease; transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
} }
.about-box:hover .icon-circle { .about-box:hover .icon-circle {
background: var(--secondary); background: linear-gradient(135deg, #0F2C59 0%, #3E51B8 100%);
transform: rotateY(180deg); /* කාඩ් එක උඩට යද්දී අයිකන් එක කැරකෙනවා */ color: #ffffff;
border-color: transparent;
transform: scale(1.12) rotate(6deg);
box-shadow: 0 10px 25px rgba(62, 81, 184, 0.35);
} }
/* ======================================================== /* ===== CTA BUTTON ===== */
Advanced CSS Scroll Animations .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 { .animate-item {
opacity: 0; opacity: 0;
will-change: transform, opacity; will-change: transform, opacity;
transition: all 0.8s cubic-bezier(0.25, 1, 0.5, 1); transition: all 0.8s cubic-bezier(0.25, 1, 0.5, 1);
} }
/* 1. පල්ලෙහා ඉඳන් උඩට එන ඇනිමේෂන් */ .fade-up-init { transform: translateY(30px); }
.fade-up-init { .slide-left-init { transform: translateX(-40px); }
transform: translateY(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 { .animate-item.animated {
opacity: 1; opacity: 1;
transform: translate(0) scale(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> </style>
<!-- HERO --> <!-- HERO SECTION -->
<section class="hero-about"> <section class="hero-about">
<div class="container"> <div class="container">
<div class="animate-item animated fade-up-init"> <div class="animate-item animated fade-up-init">
<h1 class="fw-bold display-4">About Our Institute</h1> <span class="hero-badge"><i class="fa-solid fa-graduation-cap"></i> Pioneering Automotive Academy</span>
<p class="mt-3 lead" style="max-width: 700px; margin: auto;"> <h1 class="fw-bold">Empowering Future Mobility Leaders</h1>
We are committed to delivering high-quality automotive education <p class="lead">
with practical training and industry-focused learning. 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> </p>
</div> </div>
</div> </div>
</section> </section>
<!-- ABOUT CONTENT --> <!-- FLOATING STATS COUNTER -->
<section class="py-5 overflow-hidden"> <div class="container stats-container">
<div class="container"> <div class="row g-3 justify-content-center">
<div class="row align-items-center g-5"> <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"> <div class="col-md-6 animate-item slide-left-init">
<img src="https://images.pexels.com/photos/3862130/pexels-photo-3862130.jpeg" <div class="p-4 rounded-4 bg-light border border-light-subtle h-100">
class="img-fluid rounded shadow-lg" <div class="d-flex align-items-center gap-3 mb-3">
alt="About Image"> <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> </div>
<!-- දකුණේ සිට වමට පැමිණේ --> <!-- MISSION (RIGHT COLUMN) -->
<div class="col-md-6 animate-item slide-right-init"> <div class="col-md-6 animate-item slide-right-init">
<h2 class="fw-bold mb-3">Who We Are</h2> <div class="p-4 rounded-4 bg-light border border-light-subtle h-100">
<p class="text-muted fs-5"> <div class="d-flex align-items-center gap-3 mb-3">
Our institute specializes in automotive engineering education, <div class="minimal-icon-badge bg-danger-subtle text-danger">
offering hands-on training in modern vehicle technologies, <i class="fa-solid fa-bullseye"></i>
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> </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>
</div> </div>
</section> </section>
<!-- FEATURES --> <!-- ADVANTAGES / WHY CHOOSE US -->
<section class="py-5 bg-light"> <section class="py-5 bg-light position-relative">
<div class="container"> <div class="container py-4">
<div class="text-center mb-5 animate-item fade-up-init">
<div class="section-title 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="fw-bold">Why Choose Us</h2> <h2 class="display-6 fw-bold text-dark mt-2">Why Study With AutoEdu?</h2>
<p class="text-muted">We provide the best learning experience</p> <p class="text-muted fs-5 max-width-600 mx-auto">We combine academic excellence with real-world workshop diagnostic training.</p>
</div> </div>
<div class="row g-4"> <div class="row g-4">
<!-- කාඩ් එකින් එක Zoom-in වේ -->
<div class="col-md-4 animate-item zoom-in-init" style="transition-delay: 100ms;"> <div class="col-md-4 animate-item zoom-in-init" style="transition-delay: 100ms;">
<div class="about-box text-center"> <div class="about-box text-center">
<div class="icon-circle"> <div class="icon-circle">
<i class="fa-solid fa-chalkboard-user"></i> <i class="fa-solid fa-chalkboard-user"></i>
</div> </div>
<h4 class="mt-4 fw-bold">Expert Lecturers</h4> <h4 class="fw-bold text-dark mb-3">Expert Lecturers</h4>
<p class="text-muted mb-0"> <p class="text-muted mb-0 lh-base">
Experienced industry professionals guiding your learning journey. Learn directly from veteran automotive engineers, diagnostic specialists, and TVEC certified master instructors.
</p> </p>
</div> </div>
</div> </div>
@ -195,9 +367,9 @@
<div class="icon-circle"> <div class="icon-circle">
<i class="fa-solid fa-screwdriver-wrench"></i> <i class="fa-solid fa-screwdriver-wrench"></i>
</div> </div>
<h4 class="mt-4 fw-bold">Practical Training</h4> <h4 class="fw-bold text-dark mb-3">Practical Training</h4>
<p class="text-muted mb-0"> <p class="text-muted mb-0 lh-base">
Hands-on workshop experience with real vehicles and tools. Hands-on workshop experience working on modern EFI engines, EV battery test bays, and automated gearboxes.
</p> </p>
</div> </div>
</div> </div>
@ -207,36 +379,38 @@
<div class="icon-circle"> <div class="icon-circle">
<i class="fa-solid fa-certificate"></i> <i class="fa-solid fa-certificate"></i>
</div> </div>
<h4 class="mt-4 fw-bold">Certified Courses</h4> <h4 class="fw-bold text-dark mb-3">Certified Qualifications</h4>
<p class="text-muted mb-0"> <p class="text-muted mb-0 lh-base">
Industry-recognized certifications to boost your career. Earn internationally recognized NVQ Level 4/5 diplomas and certifications that accelerate your global career.
</p> </p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</section> </section>
<!-- CTA --> <!-- CALL TO ACTION (CTA) -->
<section class="py-5 text-center bg-white overflow-hidden"> <section class="py-5 text-center bg-white overflow-hidden position-relative">
<div class="container py-4 animate-item fade-up-init"> <div class="container py-4 animate-item fade-up-init">
<h2 class="fw-bold mb-3">Start Your Automotive Career Today</h2> <div class="p-5 rounded-4 shadow-sm position-relative overflow-hidden" style="background: linear-gradient(135deg, #0F172A 0%, #1E293B 100%);">
<p class="text-muted fs-5 mb-5"> <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>
Join our institute and become a skilled automotive professional. <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> </p>
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center">
<a href="/apply" class="cta-btn shadow"> <a href="/apply" class="cta-btn">
Apply Courses Apply For Courses <i class="fa-solid fa-arrow-right"></i>
</a> </a>
</div> </div>
</div> </div>
</div>
</section> </section>
<script> <script>
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
// Scroll animations observer
const animatedElements = document.querySelectorAll('.animate-item'); const animatedElements = document.querySelectorAll('.animate-item');
const observer = new IntersectionObserver((entries) => { const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => { entries.forEach(entry => {
if (entry.isIntersecting) { 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)); 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> </script>

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -6,136 +6,184 @@
<style> <style>
body { body {
font-family: Arial, Helvetica, sans-serif; font-family: 'Segoe UI', Arial, Helvetica, sans-serif;
background: #f5f5f5; background: #F8FAFC;
color: #1E293B;
} }
:root { :root {
--primary: #5E244E; /* Premium Modern Automotive Palette */
--secondary: #8B3A74; --primary: #0F2C59;
--light: #F8F4F7; --secondary: #822424;
--secondary-hover: #6a2525;
--accent-yellow: #FFE618;
--bg-light: #F8FAFC;
--text-main: #1E293B;
--card-border: rgba(62, 81, 184, 0.12);
} }
.hero { .hero {
height: 220px; height: 240px;
background: linear-gradient(rgba(20,20,20,.55),rgba(20,20,20,.55)), 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');
url('https://images.unsplash.com/photo-1517520287167-4bbf64a00d66?auto=format&fit=crop&w=1600&q=80');
background-size: cover; background-size: cover;
background-position: center; background-position: center;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
color: white; color: white;
text-align: center;
} }
.hero h1 { .hero h1 {
font-size: 32px; font-size: 36px;
font-weight: bold; font-weight: 800;
margin: 0; margin: 0;
letter-spacing: -0.5px;
} }
.apply-area { .apply-area {
margin-top: -40px; margin-top: -50px;
margin-bottom: 40px; margin-bottom: 50px;
} }
.form-container-sm { .form-container-sm {
max-width: 820px; max-width: 850px;
margin: 0 auto; margin: 0 auto;
} }
.form-card { .form-card {
background: white; background: white;
border-radius: 10px; border-radius: 16px;
overflow: hidden; 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 { .form-header {
background: var(--primary); background: linear-gradient(135deg, #8C4242 0%, #161414fa 100%);
color: white; color: white;
padding: 15px 25px; padding: 25px 30px;
border-bottom: 3px solid var(--accent-yellow);
} }
.form-header h2 { .form-header h2 {
margin: 0; margin: 0;
font-size: 20px; font-size: 22px;
font-weight: bold; font-weight: 700;
} }
.section-title { .section-title {
background: #735D6D; background: var(--secondary);
color: white; color: white;
padding: 8px 12px; padding: 10px 16px;
margin-top: 22px; margin-top: 30px;
margin-bottom: 15px; margin-bottom: 20px;
font-size: 14px; font-size: 14px;
border-radius: 5px; border-radius: 6px;
font-weight: 600; font-weight: 600;
letter-spacing: 0.5px;
box-shadow: 0 4px 10px rgba(106, 37, 37, 0.15);
} }
.form-label { .form-label {
font-weight: 600; font-weight: 600;
font-size: 13px; font-size: 13px;
margin-bottom: 4px; margin-bottom: 6px;
color: #000;
} }
.form-control, .form-control,
.form-select { .form-select {
border-radius: 5px; border: 1px solid #cbd5e1;
padding: 6px 10px; border-radius: 8px;
font-size: 13px; 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 { .required {
color: red; color: var(--secondary-hover);
font-weight: bold;
} }
.submit-btn { .submit-btn {
background: var(--primary); background:var(--secondary);
color: white; color: white;
border: none; border: none;
padding: 8px 20px; padding: 14px 30px;
font-size: 15px; font-size: 16px;
font-weight: bold; font-weight: 700;
border-radius: 30px; border-radius: 8px;
cursor: pointer; cursor: pointer;
width: 100%; 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 { .submit-btn:hover {
background: var(--secondary); background: linear-gradient(135deg, var(--secondary) 0%, var(--secondary-hover) 100%);
transform: translateY(-1px); color: var(--accent-yellow);
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(130, 36, 36, 0.35);
} }
.mb-3-custom { .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> </style>
<div class="hero"> <div class="hero">
<div class="text-center"> <div class="text-center px-3">
<h1>Course Enrolment Form</h1> <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> </div>
<div class="container apply-area"> <div class="container apply-area">
<div class="form-container-sm"> <div class="form-container-sm">
<div class="form-card"> <div class="form-card">
<div class="form-header"> <div class="form-header">
<h2> <h2>
<i class="fa-solid fa-file-circle-check me-2"></i> <i class="fa-solid fa-file-circle-check me-2"></i>
Course Enrolment Form New Student Registration
</h2> </h2>
</div> </div>
<div class="p-4"> <div class="p-4 p-md-5">
<form action="#" method="POST" enctype="multipart/form-data">
@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 @csrf
{{-- STUDENT INFORMATION --}} {{-- STUDENT INFORMATION --}}
@ -146,32 +194,32 @@
<div class="row"> <div class="row">
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
<label class="form-label">First Name <span class="required">*</span></label> <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>
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
<label class="form-label">Last Name <span class="required">*</span></label> <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>
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
<label class="form-label">NIC / Passport</label> <label class="form-label">NIC / Passport Number</label>
<input type="text" name="nic" class="form-control"> <input type="text" name="nic" class="form-control" placeholder="Identity Document No.">
</div> </div>
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
<label class="form-label">Nationality</label> <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>
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
<label class="form-label">Address <span class="required">*</span></label> <label class="form-label">Residential Address <span class="required">*</span></label>
<input type="text" name="address" class="form-control" required> <input type="text" name="address" class="form-control" placeholder="Street address" required>
</div> </div>
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
<label class="form-label">District / City / State <span class="required">*</span></label> <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>
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
@ -198,17 +246,17 @@
<div class="row"> <div class="row">
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
<label class="form-label">Contact Number <span class="required">*</span></label> <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>
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
<label class="form-label">Alternative Contact Number</label> <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>
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
<label class="form-label">Email Address <span class="required">*</span></label> <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>
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
@ -216,7 +264,7 @@
<select name="preferred_contact_method" class="form-select"> <select name="preferred_contact_method" class="form-select">
<option selected disabled>Select Your Option</option> <option selected disabled>Select Your Option</option>
<option value="email">Email</option> <option value="email">Email</option>
<option value="phone">Phone</option> <option value="phone">Phone Call</option>
<option value="sms">SMS</option> <option value="sms">SMS</option>
</select> </select>
</div> </div>
@ -224,12 +272,12 @@
{{-- EDUCATION --}} {{-- EDUCATION --}}
<div class="section-title"> <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>
<div class="row"> <div class="row">
<div class="col-md-6 mb-3-custom"> <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"> <select name="still_at_school" class="form-select">
<option selected disabled>Select Your Option</option> <option selected disabled>Select Your Option</option>
<option value="Yes">Yes</option> <option value="Yes">Yes</option>
@ -255,7 +303,7 @@
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
<label class="form-label">School / College Name</label> <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>
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
@ -266,10 +314,10 @@
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
<label class="form-label">Examination Passed</label> <label class="form-label">Examination Passed</label>
<select name="exam_passed" class="form-select"> <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. O/L">G.C.E. O/L</option>
<option value="G.C.E. A/L">G.C.E. A/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="Certificate">Certificate</option>
<option value="Diploma">Diploma</option> <option value="Diploma">Diploma</option>
<option value="Degree">Degree</option> <option value="Degree">Degree</option>
@ -278,17 +326,17 @@
</div> </div>
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
<label class="form-label">Subjects</label> <label class="form-label">Core Subjects</label>
<input type="text" name="subjects" class="form-control" placeholder="e.g. Mathematics, Science"> <input type="text" name="subjects" class="form-control" placeholder="e.g. Mathematics, Science, Tech">
</div> </div>
<div class="col-12 mb-3-custom"> <div class="col-12 mb-3-custom">
<label class="form-label">Grades / Results</label> <label class="form-label">Grades / Academic Results Summary</label>
<textarea name="grades_results" class="form-control" rows="2" placeholder="Enter your grades or examination results"></textarea> <textarea name="grades_results" class="form-control" rows="3" placeholder="List your relevant examination grades or index summaries..."></textarea>
</div> </div>
<div class="col-12 mb-3-custom"> <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> <input type="file" name="certificates[]" class="form-control" accept=".pdf,.jpg,.jpeg,.png" multiple>
</div> </div>
</div> </div>
@ -301,24 +349,24 @@
<div class="row"> <div class="row">
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
<label class="form-label">Emergency Contact Name <span class="required">*</span></label> <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>
<div class="col-md-6 mb-3-custom"> <div class="col-md-6 mb-3-custom">
<label class="form-label">Relationship <span class="required">*</span></label> <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>
</div> </div>
{{-- TERMS AND CONDITIONS --}} {{-- 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> <input class="form-check-input" type="checkbox" id="terms" required>
<label class="form-check-label" for="terms" style="font-size: 13px;"> <label class="form-check-label fw-semibold" for="terms" style="font-size: 13px; color: #000; cursor: pointer;">
I agree to the terms and conditions <span class="required">*</span> I hereby declare that the details furnished above are true and correct to the best of my knowledge <span class="required">*</span>
</label> </label>
</div> </div>
<div class="mt-3"> <div class="mt-4">
<button type="submit" class="submit-btn">Submit Application</button> <button type="submit" class="submit-btn">Submit Application</button>
</div> </div>

View File

@ -6,20 +6,29 @@
<style> <style>
:root{ :root{
--primary:#5E244E; /* Premium Modern Automotive Palette */
--secondary:#8B3A74; --primary: #3E51B8; /* Tech Blue */
--light:#f8f4f7; --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 { body {
font-family: Arial, Helvetica, sans-serif; font-family: 'Segoe UI', Arial, sans-serif;
color: var(--text-main);
} }
.hero-contact{ .hero-contact{
min-height:50vh; min-height:50vh;
background: background:
linear-gradient(rgba(0,0,0,.7),rgba(0,0,0,.7)), 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');
url('https://images.pexels.com/photos/3184465/pexels-photo-3184465.jpeg');
background-size:cover; background-size:cover;
background-position:center; background-position:center;
display:flex; display:flex;
@ -33,37 +42,39 @@ body {
background:#fff; background:#fff;
border-radius:20px; border-radius:20px;
padding:35px; padding:35px;
box-shadow: 0 10px 30px rgba(0,0,0,.05); box-shadow: 0 10px 30px rgba(0,0,0,.04);
border: 1px solid #efeff4; border: 1px solid var(--card-border);
} }
.form-control{ .form-control{
border-radius:10px; border-radius:10px;
padding:12px; padding:12px;
border: 1px solid #ced4da; border: 1px solid #cbd5e1;
transition: all 0.3s ease; transition: all 0.3s ease;
} }
.form-control:focus { .form-control:focus {
border-color: var(--primary); border-color: var(--primary-light);
box-shadow: 0 0 0 0.25rem rgba(94, 36, 78, 0.25); box-shadow: 0 0 0 4px rgba(10, 103, 223, 0.15);
outline: 0;
} }
.btn-contact{ .btn-contact{
background:var(--primary); background: #6a2525 ;
color:#fff; color:#fff;
border-radius:10px; border-radius:10px;
padding:12px 30px; padding:12px 30px;
font-weight: 600; font-weight: 600;
transition: all 0.3s ease; transition: all 0.3s ease;
border: none; border: none;
box-shadow: 0 4px 12px rgba(62, 81, 184, 0.2);
} }
.btn-contact:hover{ .btn-contact:hover{
background:var(--secondary); background: linear-gradient(135deg, var(--secondary) 0%, var(--secondary-hover) 100%);
color:#fff; color:#fff;
transform: translateY(-2px); 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{ .info-card{
@ -72,19 +83,23 @@ body {
padding:20px; padding:20px;
text-align:center; text-align:center;
box-shadow: 0 5px 20px rgba(0,0,0,.04); box-shadow: 0 5px 20px rgba(0,0,0,.04);
border: 1px solid #efeff4; border: 1px solid var(--card-border);
transition:.3s; transition:.3s;
} }
.info-card:hover{ .info-card:hover{
transform:translateY(-5px); transform:translateY(-5px);
border-color: var(--primary); border-color: var(--primary-light);
box-shadow: 0 10px 25px rgba(94, 36, 78, 0.08); box-shadow: 0 10px 25px rgba(62, 81, 184, 0.1);
} }
.info-card i { .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); transition: all 0.8s cubic-bezier(0.25, 1, 0.5, 1);
} }
.fade-up-init { .fade-up-init {
transform: translateY(30px); transform: translateY(30px);
} }
.slide-left-init { .slide-left-init {
transform: translateX(-40px); transform: translateX(-40px);
} }
.fade-in-init { .fade-in-init {
transform: scale(0.98); transform: scale(0.98);
} }
@ -123,7 +135,7 @@ body {
<div class="container"> <div class="container">
<div class="animate-item animated fade-up-init"> <div class="animate-item animated fade-up-init">
<h1 class="fw-bold display-4">Contact Us</h1> <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>
</div> </div>
</section> </section>
@ -138,9 +150,7 @@ body {
<div class="col-md-6 animate-item slide-left-init"> <div class="col-md-6 animate-item slide-left-init">
<div class="contact-box"> <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')) @if(session('success'))
<div class="alert alert-success"> <div class="alert alert-success">
@ -148,27 +158,26 @@ body {
</div> </div>
@endif @endif
<form action="{{ route('contact.store') }}" method="POST"> <form action="{{ route('contact.store') }}" method="POST">
@csrf @csrf
<div class="mb-3"> <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> <input type="text" name="name" class="form-control" placeholder="Your Name" required>
</div> </div>
<div class="mb-3"> <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> <input type="email" name="email" class="form-control" placeholder="Your Email" required>
</div> </div>
<div class="mb-3"> <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> <input type="text" name="subject" class="form-control" placeholder="Subject" required>
</div> </div>
<div class="mb-3"> <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> <textarea name="message" rows="5" class="form-control" placeholder="Your Message" required></textarea>
</div> </div>
@ -181,7 +190,7 @@ Send Message
</div> </div>
</div> </div>
<!-- Info Cards -->
<div class="col-md-6 animate-item fade-in-init"> <div class="col-md-6 animate-item fade-in-init">
<div class="info-card mb-3"> <div class="info-card mb-3">
@ -217,37 +226,17 @@ Send Message
<!-- MAP --> <!-- MAP -->
<section class="pb-5"> <section class="pb-5">
<div class="container"> <div class="container animate-item fade-up-init">
<!-- <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> -->
<iframe <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" 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%" 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" 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="" allowfullscreen=""
loading="lazy"> loading="lazy">
</iframe> </iframe>
</div> </div>
</section> --> </section>
<script> <script>
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
@ -267,5 +256,7 @@ document.addEventListener('DOMContentLoaded', function () {
animatedElements.forEach(el => observer.observe(el)); animatedElements.forEach(el => observer.observe(el));
}); });
</script> </script>
|
@endsection @endsection

File diff suppressed because it is too large Load Diff

View File

@ -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>

View File

@ -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'); -->

View File

@ -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>

View File

@ -4,92 +4,220 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="{{ csrf_token() }}"> <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 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="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> <style>
body { body {
font-family: 'Segoe UI', sans-serif; font-family: 'Inter', 'Segoe UI', sans-serif;
background: #f5f7fb; 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 { .navbar {
background: #5E244E; background:#2D355B;
/* background: #3E51B8; */
z-index: 1000; z-index: 1000;
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; 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; 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 { .navbar-brand {
color: white; color: white;
font-weight: bold; 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 { .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 { .nav-link {
color: rgba(255, 255, 255, 0.85) !important; color: rgba(255, 255, 255, 0.85) !important;
margin-left: 20px; margin-left: 2px;
transition: 0.2s ease; padding: 9px 16px !important;
font-weight:bold; 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:hover,
.nav-link.active-page { .nav-link.active-page {
color: #ffc107 !important; color: #FFEA85 !important;
font-weight:bold; 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 { .site-footer {
background: #2F1027; background:#1F2541;
color: #f1e9ee; /* background: #182EA4; */
padding: 60px 0 30px; color: #ffffff;
padding: 64px 0 30px;
border-top: 3px solid #FFEA85;
} }
.site-footer h4 { .site-footer h4 {
color: #fff; color: #FFEA85;
font-weight: 700; font-weight: 700;
margin-bottom: 18px; margin-bottom: 20px;
letter-spacing: 0.02em;
font-size: 16px;
text-transform: uppercase;
} }
.site-footer p { .site-footer p {
color: #d8c7d3; color: #f1f3f9;
line-height: 1.6; 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 { .user-dropdown-toggle {
cursor: pointer; cursor: pointer;
color: white; color: white;
display: flex; display: flex;
flex-direction: column;
align-items: center; align-items: center;
gap: 8px; justify-content: center;
gap: 2px;
user-select: none; user-select: none;
text-decoration: none !important; text-decoration: none !important;
line-height: 1.1;
} }
.user-dropdown-toggle:hover { .user-dropdown-toggle:hover {
color: #ffc107; color: #FFEA85;
} }
.user-profile-name { .user-profile-name {
font-weight: 600; font-weight: 500;
font-size: 14px; font-style: italic;
max-width: 120px; font-size: 11px;
max-width: 110px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; 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 { .footer-links li {
@ -97,48 +225,68 @@
} }
.footer-links a { .footer-links a {
color: #d8c7d3; color: #f1f3f9;
text-decoration: none; text-decoration: none;
transition: .2s; transition: .2s;
} }
.footer-links a:hover { .footer-links a:hover {
color: #FFC107; color: #FFEA85;
padding-left: 4px; padding-left: 4px;
} }
.footer-contact li { .footer-contact li {
margin-bottom: 14px; margin-bottom: 14px;
color: #d8c7d3; color: #f1f3f9;
display: flex; display: flex;
align-items: flex-start; align-items: center;
gap: 10px; gap: 12px;
} }
.footer-contact i { .footer-contact i {
color: #FFC107; color: #FFEA85;
margin-top: 3px; 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 { .footer-contact a {
color: #d8c7d3; color: #f1f3f9;
text-decoration: none; text-decoration: none;
} }
.footer-contact a:hover { .footer-contact a:hover {
color: #FFC107; color: #FFEA85;
} }
.site-footer hr { .site-footer hr {
border-color: rgba(255,255,255,.15); border-color: rgba(255,255,255,.2);
margin: 40px 0 20px; margin: 40px 0 20px;
} }
.footer-bottom { .footer-bottom {
color: #b8a6b3; color: #e2e5f3;
font-size: 14px; 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 { .animate {
animation-duration: 0.2s; animation-duration: 0.2s;
animation-fill-mode: both; animation-fill-mode: both;
@ -184,7 +332,7 @@
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </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"> <ul class="navbar-nav ms-auto mb-2 mb-lg-0 align-items-lg-center">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link {{ request()->is('/') ? 'active-page' : '' }}" href="/">Home</a> <a class="nav-link {{ request()->is('/') ? 'active-page' : '' }}" href="/">Home</a>
@ -207,7 +355,7 @@
@php @php
$displayName = Auth::user()->first_name . ' ' . Auth::user()->last_name; $displayName = Auth::user()->first_name . ' ' . Auth::user()->last_name;
@endphp @endphp
<div class="dropdown" style="padding-left:325px;"> <div class="dropdown">
<a class="user-dropdown-toggle text-white" <a class="user-dropdown-toggle text-white"
href="#" href="#"
role="button" role="button"
@ -234,9 +382,10 @@
</ul> </ul>
</div> </div>
@else @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="/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> </div>
@endif @endif
</li> </li>
@ -245,8 +394,6 @@
</div> </div>
</nav> </nav>
<main> <main>
@yield('content') @yield('content')
</main> </main>
@ -257,6 +404,12 @@
<div class="col-md-4"> <div class="col-md-4">
<h4>Automobile Academic</h4> <h4>Automobile Academic</h4>
<p>Providing excellence in Automotive Engineering Education, Innovation and Research.</p> <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>
<div class="col-md-4"> <div class="col-md-4">

View File

@ -4,77 +4,98 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="{{ csrf_token() }}"> <meta name="csrf-token" content="{{ csrf_token() }}">
<title>Responsive Student Portal</title> <title>@yield('title', 'Student Portal - Automobile Academic')</title>
<!-- Font Awesome Icons --> <!-- Google Fonts & Font Awesome Icons & Bootstrap 5 -->
<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=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"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style> <style>
/* Global Root Variables */
:root { :root {
--primary: #000000; --theme-navy: #1E233E;
--background: #f5f6fb; --theme-footer-navy: #15182C;
--theme-red: #822424;
--theme-red-hover: #df2c3e;
--theme-yellow: #FFEA85;
--theme-bg: #F4F6F9;
--sidebar-width: 260px; --sidebar-width: 260px;
--text-color: #333333; --text-dark: #1E293B;
--sidebar-bg: #5E244E;
} }
* { * {
margin: 0; margin: 0;
padding: 0; padding: 0;
box-sizing: border-box; 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 { body {
background-color: var(--background); background-color: var(--theme-bg);
color: var(--text-color); color: var(--text-dark);
display: flex; display: flex;
min-height: 100vh; min-height: 100vh;
overflow-x: hidden; overflow-x: hidden;
} }
/* ---------- Sidebar Style ---------- */
.sidebar { .sidebar {
width: var(--sidebar-width); width: var(--sidebar-width);
height: 100vh; height: 100vh;
background: var(--sidebar-bg); background: linear-gradient(180deg, #1E233E 0%, #15182C 100%);
color: #fff; color: #fff;
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
padding: 24px 0; padding: 24px 0;
transition: all 0.3s ease; transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
z-index: 1030; z-index: 1030;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
box-shadow: 4px 0 20px rgba(0,0,0,0.08);
} }
.sidebar .brand { .sidebar .brand {
padding: 0 24px 24px; padding: 0 20px 22px;
font-weight: 700; 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; font-size: 1.2rem;
border-bottom: 1px solid rgba(255,255,255,.12); box-shadow: 0 6px 16px rgba(130, 36, 36, 0.35);
margin-bottom: 12px;
display: flex;
align-items: center;
} }
/* User Profile Section inside Sidebar */ .brand-text {
.sidebar-user-profile { display: flex;
padding: 15px 24px; flex-direction: column;
border-bottom: 1px solid rgba(255,255,255,.12); line-height: 1.1;
margin-bottom: 15px;
} }
.sidebar-user-profile .dropdown-toggle { .brand-text span {
display: flex; font-weight: 800;
align-items: center; font-size: 1.25rem;
gap: 10px; color: #ffffff;
color: #fff; letter-spacing: -0.5px;
text-decoration: none; }
font-size: 0.95rem;
.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 { .sidebar .nav {
@ -82,63 +103,204 @@
flex-direction: column; flex-direction: column;
flex-grow: 1; flex-grow: 1;
overflow-y: auto; overflow-y: auto;
padding: 0 14px;
gap: 4px;
} }
.sidebar .nav-link { .sidebar .nav-link {
color: rgba(255,255,255,.75); color: rgba(255, 255, 255, 0.75);
padding: 14px 24px; padding: 13px 18px;
font-size: .95rem; font-size: 0.93rem;
font-weight: 600;
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12px; gap: 14px;
transition: .2s; transition: all 0.25s cubic-bezier(0.16, 1, 0.3, 1);
border-left: 3px solid transparent; border-radius: 14px;
text-decoration: none; text-decoration: none;
position: relative;
} }
.sidebar .nav-link i { .sidebar .nav-link i {
width: 20px; width: 22px;
text-align: center; text-align: center;
font-size: 1.1rem;
transition: transform 0.25s ease, color 0.25s ease;
} }
.sidebar .nav-link:hover { .sidebar .nav-link:hover {
background: rgba(255,255,255,.06); background: rgba(255, 255, 255, 0.08);
color: #fff; 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 { .sidebar .nav-link.active {
background: rgba(255,255,255,.1); background: linear-gradient(90deg, rgba(255, 234, 133, 0.16) 0%, rgba(255, 234, 133, 0.06) 100%);
color: #fff; color: var(--theme-yellow) !important;
border-left: 3px solid #fff; font-weight: 700;
font-weight: 600; 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 { .sidebar .nav-link.active i {
color: rgba(255,255,255,.6); color: var(--theme-yellow);
}
.sidebar-user-profile {
padding: 16px 18px;
border-top: 1px solid rgba(255,255,255,.08);
margin-top: auto; 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; 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 { .main {
margin-left: var(--sidebar-width); margin-left: var(--sidebar-width);
width: calc(100% - var(--sidebar-width)); width: calc(100% - var(--sidebar-width));
min-height: 100vh; min-height: 100vh;
padding: 40px; padding: 32px 40px;
background: var(--background); background: var(--theme-bg);
transition: all 0.3s ease; 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 { .mobile-header {
display: none; display: none;
background: #fff; background: var(--theme-navy);
padding: 15px 20px; color: #ffffff;
box-shadow: 0 2px 5px rgba(0,0,0,0.05); padding: 12px 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
position: fixed; position: fixed;
@ -151,21 +313,24 @@
.sidebar-toggle { .sidebar-toggle {
background: none; background: none;
border: none; border: none;
font-size: 1.5rem; font-size: 1.4rem;
cursor: pointer; cursor: pointer;
color: var(--sidebar-bg); color: #ffffff;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.sidebar-toggle:hover {
color: var(--theme-yellow);
}
.mobile-brand { .mobile-brand {
font-weight: 700; font-weight: 700;
font-size: 1.1rem; font-size: 1.1rem;
color: #333; color: #ffffff;
} }
/* Overlay Background when sidebar open on Mobile */
.sidebar-overlay { .sidebar-overlay {
display: none; display: none;
position: fixed; position: fixed;
@ -173,7 +338,7 @@
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
background: rgba(0,0,0,0.4); background: rgba(0,0,0,0.5);
z-index: 1025; z-index: 1025;
opacity: 0; opacity: 0;
transition: opacity 0.3s ease; transition: opacity 0.3s ease;
@ -184,7 +349,6 @@
opacity: 1; opacity: 1;
} }
/* ---------- Responsive Media Queries (Mobile & Tablets) ---------- */
@media (max-width: 991px) { @media (max-width: 991px) {
.sidebar { .sidebar {
left: calc(-1 * var(--sidebar-width)); left: calc(-1 * var(--sidebar-width));
@ -196,7 +360,7 @@
.main { .main {
margin-left: 0; margin-left: 0;
padding: 90px 20px 20px 20px; padding: 85px 20px 20px 20px;
width: 100%; width: 100%;
} }
@ -213,22 +377,23 @@
<button class="sidebar-toggle" id="toggleBtn" aria-label="Toggle Sidebar"> <button class="sidebar-toggle" id="toggleBtn" aria-label="Toggle Sidebar">
<i class="fa-solid fa-bars"></i> <i class="fa-solid fa-bars"></i>
</button> </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"> <div class="mobile-user-profile">
@if(Auth::check()) @if(session()->has('student_id'))
<div class="dropdown"> <div class="dropdown">
<a class="text-dark no-toggle-icon" href="#" role="button" id="userMenuMobile" data-bs-toggle="dropdown" aria-expanded="false"> <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: 35px; color: var(--sidebar-bg);"></i> <i class="fa-solid fa-circle-user" style="font-size: 24px; color: var(--theme-yellow);"></i>
<strong>{{ Auth::user()->first_name }}</strong> <span class="fst-italic" style="font-size: 11px;">{{ session('student_name') }}</span>
</a> </a>
<ul class="dropdown-menu dropdown-menu-end shadow" aria-labelledby="userMenuMobile"> <ul class="dropdown-menu dropdown-menu-end shadow" aria-labelledby="userMenuMobile">
<li class="px-3 py-2 "> <li>
<!-- <small class="text-muted">Signed in as</small><br> --> <a class="dropdown-item" href="{{ route('StudentProfile') }}">
<!-- <strong>{{ Auth::user()->first_name }}</strong> --> <i class="fa-solid fa-user me-2"></i> Profile
</a>
</li> </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><hr class="dropdown-divider"></li>
<li> <li>
<button type="button" onclick="submitLogout()" class="dropdown-item text-danger w-100 text-start border-0 bg-transparent"> <button type="button" onclick="submitLogout()" class="dropdown-item text-danger w-100 text-start border-0 bg-transparent">
@ -238,142 +403,166 @@
</ul> </ul>
</div> </div>
@else @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 @endif
</div> </div>
</header> </header>
<!-- Overlay dim background element -->
<div class="sidebar-overlay" id="sidebarOverlay"></div> <div class="sidebar-overlay" id="sidebarOverlay"></div>
<!-- Sidebar Navigation --> <!-- Sidebar Navigation -->
<aside class="sidebar" id="sidebar"> <aside class="sidebar" id="sidebar">
<div class="brand"> <div class="brand">
<i class="fa-solid fa-graduation-cap"></i>&nbsp;&nbsp;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> </div>
<!-- Sidebar Active User Profile Details (Desktop View) -->
<nav class="nav"> <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 <i class="fa-solid fa-gauge"></i> Dashboard
</a> </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 <i class="fa-solid fa-book"></i> My Courses
</a> </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 <i class="fa-solid fa-calendar-days"></i> Class Timetable
</a> </a>
<!-- <a href="/Assignments" class="nav-link"> <a href="/results" class="nav-link {{ request()->is('results*') ? 'active' : '' }}">
<i class="fa-solid fa-file-lines"></i>Assignments
</a> -->
<a href="/results" class="nav-link">
<i class="fa-solid fa-square-poll-vertical"></i> Exam Results <i class="fa-solid fa-square-poll-vertical"></i> Exam Results
</a> </a>
<a href="/Studentguidelines" class="nav-link {{ request()->is('Studentguidelines*') ? 'active' : '' }}">
<a href="/Studentguidelines" class="nav-link">
<i class="fa-solid fa-book-open"></i> Student Guidelines <i class="fa-solid fa-book-open"></i> Student Guidelines
</a> </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 <i class="fa-solid fa-comments"></i> Feedback & Complain
</a> </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 <i class="fa-solid fa-user"></i> Student Profile
</a> </a>
</nav> </nav>
<div class="sidebar-user-profile"> <div class="sidebar-user-profile">
@if(Auth::check()) @if(session()->has('student_id'))
@php <div class="dropdown dropup">
$displayName = Auth::user()->first_name . ' ' . Auth::user()->last_name; <a class="user-dropdown-toggle dropdown-toggle" href="#" role="button" id="userMenuDesktop" data-bs-toggle="dropdown" aria-expanded="false">
@endphp <div class="user-avatar-badge-sm">
<div class="dropdown"> {{ strtoupper(substr(session('student_name', 'S'), 0, 1)) }}
<a class="dropdown-toggle" href="#" role="button" id="userMenuDesktop" data-bs-toggle="dropdown" aria-expanded="false"> </div>
<i class="fa-solid fa-circle-user" style="font-size: 24px;"></i> <div class="user-info-text">
<span class="user-profile-name text-truncate" style="max-width: 160px;">{{ $displayName }}</span> <span class="user-name-text">{{ session('student_name', 'Student') }}</span>
<span class="user-email-text">Active Session</span>
</div>
</a> </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> <li>
<a class="dropdown-item" href="/StudentProfile"> <a class="dropdown-item user-dropdown-item py-2.5 px-3 rounded-3" href="{{ route('StudentProfile') }}">
<i class="fa-solid fa-user me-2"></i> Profile <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> </a>
</li> </li>
<li><hr class="dropdown-divider"></li> <li><hr class="dropdown-divider border-white opacity-10 my-1"></li>
<li> <li>
<a href="#" onclick="submitLogout(); return false;" class="nav-link logout-link mt-auto" style="color:black;"> <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">
<i class="fa-solid fa-right-from-bracket"></i>Logout <div class="dropdown-item-icon-red">
</a> <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> </li>
</ul> </ul>
</div> </div>
@else @else
<div class="d-flex gap-2 px-2"> <div class="d-flex gap-2">
<a href="/signin" class="btn btn-outline-light btn-sm w-50">Sign In</a> <a href="/" class="btn btn-outline-light btn-sm w-100 rounded-pill">Sign In</a>
<a href="/signup" class="btn btn-warning btn-sm w-50">Register</a>
</div> </div>
@endif @endif
</div> </div>
</aside> </aside>
<!-- Main Content Area -->
<main class="main"> <main class="main">
@yield('content') @yield('content')
</main> </main>
<!-- Sidebar Toggle JavaScript --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script> <script>
// Sidebar Toggle Logic
const toggleBtn = document.getElementById('toggleBtn'); const toggleBtn = document.getElementById('toggleBtn');
const sidebar = document.getElementById('sidebar'); const sidebar = document.getElementById('sidebar');
const overlay = document.getElementById('sidebarOverlay'); const overlay = document.getElementById('sidebarOverlay');
// Function to toggle sidebar view if(toggleBtn) {
toggleBtn.addEventListener('click', () => { toggleBtn.addEventListener('click', () => {
sidebar.classList.toggle('show'); sidebar.classList.toggle('show');
overlay.classList.toggle('show'); overlay.classList.toggle('show');
}); });
}
// Close sidebar if user clicks outside of it if(overlay) {
overlay.addEventListener('click', () => { overlay.addEventListener('click', () => {
sidebar.classList.remove('show'); sidebar.classList.remove('show');
overlay.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() { function submitLogout() {
const tokenEl = document.querySelector('meta[name="csrf-token"]'); 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', { fetch('/studentlogout', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept': 'application/json', 'Accept': 'application/json',
'X-CSRF-TOKEN': tokenEl ? tokenEl.getAttribute('content') : '' 'X-CSRF-TOKEN': csrfToken
} }
}) })
.then(res => { .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(); return res.json();
}) })
.then(data => { .then(data => {
if (data.success) { if (data && data.success) {
alert('Logged out successfully!'); window.location.href = '/';
window.location.href = '/students';
} else { } else {
alert('Logout failed. Please try again.'); alert('Logout failed. Please try again.');
} }
}) })
.catch(err => { .catch(err => {
console.error('Error:', err); console.error('Logout Error:', err);
alert('Server side error occurred during logout.'); alert('An error occurred during logout.');
}); });
} }

View File

@ -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;">
&copy; {{ date('Y') }} Academy. All rights reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@ -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>

View File

@ -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

View File

@ -1,371 +1,106 @@
@extends('layouts.studentportalnav') @extends('layouts.studentportalnav')
@section('title', 'My Course') @section('title', 'My Courses & Modules')
@section('content') @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> <style>
:root { :root {
--purple-main: #5E244E; --theme-navy: #2D355B;
--purple-dark: #4a1c3e; --theme-red: #822424;
--purple-light: #744a68; --bg-light: #F6F6F6;
--gold-accent: #D4AF37;
--gold-hover: #b8972e;
--bg-light: #f8fafc;
--white: #ffffff; --white: #ffffff;
} }
body { background: var(--bg-light); font-family: 'Segoe UI', sans-serif; }
body { .course-header {
background: var(--bg-light); background: linear-gradient(135deg, #2B293F 0%, #94A6F959 100%);
font-family: 'Poppins', sans-serif; color: var(--white);
}
.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;
border-radius: 12px; border-radius: 12px;
font-size: 18px; padding: 20px;
background: rgba(94, 36, 78, 0.08); margin-bottom: 15px;
color: var(--purple-main); border-left: 5px solid var(--theme-red);
} }
/* Modules Card */
.module-card { .module-card {
border: 1px solid rgba(94, 36, 78, 0.06) !important; border: 1px solid #e2e8f0;
border-radius: 16px !important; border-radius: 10px;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
background: var(--white); background: var(--white);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.02) !important; transition: all 0.3s ease;
} }
.semester-badge {
.module-card:hover { background-color: var(--theme-navy);
transform: translateY(-5px); color: #fff;
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 {
font-size: 11px; font-size: 11px;
font-weight: 600; padding: 4px 10px;
padding: 5px 14px; border-radius: 20px;
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;
}
} }
</style> </style>
<div class="main-portal-content"> <div class="main-portal-content p-3">
<div class="container-fluid"> <div class="container-fluid">
<!-- Hero Section --> <h3 class="fw-bold mb-4" style="color: var(--theme-navy);">My Assigned Courses</h3>
<div class="hero">
<div class="row align-items-center"> @if(count($courses) > 0)
<div class="col-lg-9 col-md-8 text-start"> @foreach($courses as $courseId => $courseItems)
<h1 class="fw-bold display-6 mb-2">Diploma in Automotive Engineering</h1> @php
<p class="lead mb-4 small opacity-75">Welcome back! Continue your learning journey and complete all modules.</p> $firstItem = $courseItems->first();
<a href="#" class="btn btn-continue px-4 py-2 fw-semibold shadow-sm"> @endphp
<i class="fa fa-play me-2"></i> Continue Learning
<!-- 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> </a>
</div> </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> </div>
</div> </div>
@else
<!-- 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">
<div class="col-12"> <div class="col-12">
<div class="info-box d-flex align-items-center"> <div class="alert alert-light border">No modules found for this course.</div>
<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> </div>
@endif
@endforeach
</div> </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>
@endif
<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 -->
</div> </div>
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
@endsection @endsection

View File

@ -2,89 +2,144 @@
@section('content') @section('content')
<style> <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%); :root {
padding: 1.25rem 1.5rem; --primary-navy: #0F2C59;
border-top-left-radius: 12px !important; --accent-red: #822424;
border-top-right-radius: 12px !important; --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 { .profile-info-row {
padding: 0.9rem 0; padding: 1.1rem 0;
border-bottom: 1px solid #f1f1f4; border-bottom: 1px solid #f1f5f9;
transition: background 0.2s ease;
} }
.profile-info-row:hover {
background-color: #f8fafc;
}
.profile-info-row:last-of-type { .profile-info-row:last-of-type {
border-bottom: none; border-bottom: none;
} }
.profile-label { .profile-label {
color: #6c757d; color: var(--text-muted);
font-weight: 600; font-weight: 600;
font-size: 0.95rem; font-size: 0.95rem;
} }
.profile-value { .profile-value {
color: #212529; color: var(--text-main);
font-weight: 500; font-weight: 600;
font-size: 0.95rem; font-size: 1rem;
} }
/* ===== Theme Buttons ===== */
.btn-edit { .btn-edit {
background-color: #5c1d5c; background-color: var(--accent-red);
color: white; color: #ffffff;
border-radius: 6px; border-radius: 30px;
padding: 0.5rem 1.5rem; padding: 0.6rem 2rem;
font-weight: 500; font-weight: 600;
transition: all 0.2s ease; transition: all 0.3s ease;
border: none; border: none;
text-decoration: none; text-decoration: none;
} }
.btn-edit:hover { .btn-edit:hover {
background-color: #3d0c3d; background-color: var(--accent-red-hover);
color: white; color: #ffffff;
box-shadow: 0 4px 10px rgba(92, 29, 92, 0.3); 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> </style>
<div class="container mt-5 mb-5"> <div class="container py-5">
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-8"> <div class="col-md-8">
{{-- Alert Success Message --}}
@if(session('success')) @if(session('success'))
<div class="alert alert-success alert-dismissible fade show mb-4" role="alert" style="border-radius: 8px;"> <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="bi bi-check-circle-fill me-2"></i> {{ session('success') }} <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> <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div> </div>
@endif @endif
{{-- Main Profile Card --}}
<div class="card profile-card"> <div class="card profile-card">
<!-- Purple Header --> <!-- Navy Header -->
<div class="card-header profile-header text-white"> <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;">User Profile Dashboard</h4> <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>
<div class="card-body p-4"> <div class="card-body p-4 p-md-5">
<!-- Name -->
<!-- Full Name -->
<div class="row profile-info-row align-items-center"> <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 class="col-md-8 profile-value">{{ $user->first_name . ' ' . $user->last_name }}</div>
</div> </div>
<!-- Email --> <!-- Email Address -->
<div class="row profile-info-row align-items-center"> <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 class="col-md-8 profile-value">{{ $user->email }}</div>
</div> </div>
<!-- Phone --> <!-- Phone Number -->
<div class="row profile-info-row align-items-center"> <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"> <div class="col-md-8 profile-value">
{{ $user->phone ?? 'Not Provided' }} {{ $user->phone ?? 'Not Provided' }}
</div> </div>
@ -92,7 +147,9 @@
<!-- Created At --> <!-- Created At -->
<div class="row profile-info-row align-items-center"> <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"> <div class="col-md-8 profile-value text-muted">
{{ $user->created_at ? $user->created_at->format('Y-m-d H:i') : 'N/A' }} {{ $user->created_at ? $user->created_at->format('Y-m-d H:i') : 'N/A' }}
</div> </div>
@ -100,44 +157,42 @@
<!-- Updated At --> <!-- Updated At -->
<div class="row profile-info-row align-items-center"> <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"> <div class="col-md-8 profile-value text-muted">
{{ $user->updated_at ? $user->updated_at->format('Y-m-d H:i') : 'N/A' }} {{ $user->updated_at ? $user->updated_at->format('Y-m-d H:i') : 'N/A' }}
</div> </div>
</div> </div>
<!-- Edit Button --> <!-- Edit Profile Trigger Button -->
<div class="mt-4 text-end"> <div class="mt-4 pt-2 text-end">
<!-- <a href="#" class="btn btn-edit">Edit Profile</a> --> <button type="button" class="btn btn-edit shadow-sm" data-bs-toggle="modal" data-bs-target="#editProfileModal">
<div class="mt-4 text-end"> <i class="fa-solid fa-pen-to-square me-2"></i>Edit Profile
<button type="button" class="btn btn-edit" data-bs-toggle="modal" data-bs-target="#editProfileModal">
Edit Profile
</button> </button>
</div> </div>
</div> </div>
</div> </div>
</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 fade" id="editProfileModal" tabindex="-1" aria-labelledby="editProfileModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered"> <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) --> <!-- Modal Header (Navy Theme) -->
<div class="modal-header text-white" style="background: linear-gradient(135deg, #3d0c3d 0%, #5c1d5c 100%);"> <div class="modal-header text-white" style="background: linear-gradient(135deg, #0F2C59 0%, #1a3d73 100%);">
<h5 class="modal-title fw-bold" id="editProfileModalLabel">Update Profile Details</h5> <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> <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<!-- Update Form -->
<form action="{{ route('profile.update') }}" method="POST"> <form action="{{ route('profile.update') }}" method="POST">
@csrf @csrf
@method('PUT') @method('PUT')
@ -146,31 +201,32 @@
<!-- First Name Input --> <!-- First Name Input -->
<div class="mb-3"> <div class="mb-3">
<label for="first_name" class="form-label fw-bold" style="color: #6c757d;">First Name</label> <label for="first_name" class="form-label fw-semibold small" style="color: var(--text-muted);">First Name</label>
<input type="text" class="form-control" id="first_name" name="first_name" value="{{ $user->first_name }}" required> <input type="text" class="form-control form-control-lg fs-6" id="first_name" name="first_name" value="{{ $user->first_name }}" required>
</div> </div>
<!-- Last Name Input --> <!-- Last Name Input -->
<div class="mb-3"> <div class="mb-3">
<label for="last_name" class="form-label fw-bold" style="color: #6c757d;">Last Name</label> <label for="last_name" class="form-label fw-semibold small" style="color: var(--text-muted);">Last Name</label>
<input type="text" class="form-control" id="last_name" name="last_name" value="{{ $user->last_name }}" required> <input type="text" class="form-control form-control-lg fs-6" id="last_name" name="last_name" value="{{ $user->last_name }}" required>
</div> </div>
<!-- Phone Input --> <!-- Phone Input -->
<div class="mb-3"> <div class="mb-3">
<label for="phone" class="form-label fw-bold" style="color: #6c757d;">Phone Number</label> <label for="phone" class="form-label fw-semibold small" style="color: var(--text-muted);">Phone Number</label>
<input type="text" class="form-control" id="phone" name="phone" value="{{ $user->phone }}"> <input type="text" class="form-control form-control-lg fs-6" id="phone" name="phone" value="{{ $user->phone }}">
</div> </div>
</div> </div>
<!-- Modal Footer Buttons --> <!-- Modal Footer -->
<div class="modal-footer bg-light"> <div class="modal-footer bg-light px-4">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> <button type="button" class="btn btn-secondary border-0 rounded-3" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn text-white" style="background-color: #5c1d5c;">Save Changes</button> <button type="submit" class="btn btn-save rounded-3">Save Changes</button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
@endsection

View File

@ -4,525 +4,420 @@
@section('content') @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> <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 { body {
background:#f6f7fb; font-family: 'Poppins', sans-serif;
background: var(--bg-light);
} }
/* ======================= /* =======================
Hero Hero Section
======================= */ ======================= */
.result-hero { .result-hero {
background: linear-gradient(135deg, #2B293F 0%, #94A6F959 100%) !important;
background:linear-gradient(135deg,#5E244E,#4a1c3e); color: var(--white);
color:#fff; border-radius: 16px;
border-radius:20px; padding: 35px 30px;
padding:40px;
margin-bottom: 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 { .result-hero h2 {
font-weight: 700; font-weight: 700;
} }
.result-hero p { .result-hero p {
color: rgba(255, 255, 255, 0.85);
color:#ddd;
margin-bottom: 0; margin-bottom: 0;
} }
/* ======================= /* =======================
Summary Cards Summary Cards
======================= */ ======================= */
.summary-card { .summary-card {
background: var(--white);
background:#fff; border: 1px solid #e2e8f0;
border:none; border-radius: 16px;
border-radius:20px;
padding: 25px; padding: 25px;
text-align: center; text-align: center;
box-shadow:0 10px 25px rgba(0,0,0,.08); box-shadow: 0 4px 15px rgba(0, 0, 0, .04);
transition:.3s; transition: all 0.3s ease;
} }
.summary-card:hover { .summary-card:hover {
transform: translateY(-4px);
transform:translateY(-5px); border-color: var(--theme-navy);
box-shadow: 0 10px 22px rgba(0, 0, 0, 0.08);
} }
.summary-card i { .summary-card i {
font-size: 36px;
font-size:40px; color: var(--theme-red);
color:#5E244E; margin-bottom: 12px;
margin-bottom:15px;
} }
.summary-card h3 { .summary-card h3 {
color: var(--theme-navy);
color:#5E244E;
font-weight: 700; font-weight: 700;
margin-bottom: 4px;
} }
.summary-card small { .summary-card small {
color: #64748b;
color:#777; font-weight: 500;
} }
/* ======================= /* =======================
Result Table Result Table
======================= */ ======================= */
.result-card { .result-card {
margin-top: 30px;
margin-top:35px; background: var(--white);
background:#fff; border: 1px solid #e2e8f0;
border-radius:20px; border-radius: 16px;
overflow: hidden; overflow: hidden;
box-shadow:0 10px 30px rgba(0,0,0,.08); box-shadow: 0 4px 15px rgba(0, 0, 0, .04);
} }
.table-head { .table-head {
background: var(--theme-navy);
background:#5E244E; color: var(--white);
color:#fff;
padding: 18px 25px; padding: 18px 25px;
} }
.table { .table {
margin-bottom: 0; margin-bottom: 0;
} }
.table th { .table th {
background: #f8fafc;
background:#744a68; color: var(--theme-navy);
color:#fff; font-weight: 600;
border:none; border-bottom: 2px solid #e2e8f0;
padding: 14px 20px;
} }
.table td { .table td {
vertical-align: middle; vertical-align: middle;
padding: 14px 20px;
} }
.grade { .grade {
padding: 5px 14px;
padding:7px 15px;
border-radius: 30px; border-radius: 30px;
font-weight: 600; font-weight: 600;
color:#fff; font-size: 13px;
color: var(--white);
display: inline-block; display: inline-block;
} }
.a{ .grade.a {
background: var(--theme-navy);
background:#28a745;
} }
.b{ .grade.b {
background: var(--theme-red);
background:#17a2b8;
} }
.c{ .grade.c {
background: #e67e22;
background:#ffc107;
color:#222;
} }
.fail{ .grade.fail {
background: #dc3545; background: #dc3545;
}
.status-pass {
color: #198754;
font-weight: 600;
}
.status-fail {
color: #dc3545;
font-weight: 600;
} }
/* ======================= /* =======================
Progress Progress
======================= */ ======================= */
.progress { .progress {
height: 10px; height: 10px;
border-radius: 20px; 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 { .download-card {
margin-top: 30px; margin-top: 30px;
background:#4a1c3e; background: linear-gradient(135deg, #2B293F 0%, #94A6F959 100%) !important;
color:#fff; color: var(--white);
border-radius:20px; border-radius: 16px;
padding: 30px; padding: 30px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
flex-wrap: wrap; flex-wrap: wrap;
gap: 15px;
box-shadow: 0 8px 25px rgba(31, 37, 65, 0.15);
} }
.download-card h4 { .download-card h4 {
color: var(--theme-yellow);
color:#d4af37;
font-weight: 700; font-weight: 700;
margin-bottom: 6px;
} }
.btn-result { .btn-result {
background-color: var(--theme-red) !important;
background:#d4af37; color: var(--white) !important;
color:#fff;
border: none; border: none;
border-radius:50px; border-radius: 8px;
padding:12px 30px; padding: 10px 24px;
font-weight: 600; font-weight: 600;
transition: all 0.2s ease;
} }
.btn-result:hover { .btn-result:hover {
background-color: var(--theme-red-hover) !important;
background:#c49d20; color: var(--white) !important;
color:#fff;
} }
@media(max-width:768px) {
.result-hero {
padding: 25px;
}
}
</style> </style>
<div class="container py-4"> <div class="container py-4">
<!-- Hero --> <!-- Printable Area Container -->
<div id="pdf-download-area">
<!-- Hero Section -->
<div class="result-hero"> <div class="result-hero">
<h2> <h2>
<i class="fas fa-award me-2" style="color: var(--theme-yellow);"></i>
<i class="fas fa-award"></i>
Academic Results Academic Results
</h2> </h2>
<p> <p>
View your examination results and overall academic performance.
View your examination results and academic performance.
</p> </p>
</div> </div>
<!-- Summary --> <!-- Summary Cards -->
<div class="row g-4">
<div class="row"> <div class="col-md-4">
<div class="col-md-4 mb-4">
<div class="summary-card"> <div class="summary-card">
<i class="fas fa-chart-line"></i> <i class="fas fa-chart-line"></i>
<h3>{{ $averageMarks ?? 0 }}%</h3>
<h3>82%</h3>
<small>Overall Average</small> <small>Overall Average</small>
</div>
</div> </div>
</div> <div class="col-md-4">
<div class="col-md-4 mb-4">
<div class="summary-card"> <div class="summary-card">
<i class="fas fa-medal"></i> <i class="fas fa-medal"></i>
<h3>{{ $gpa ?? '3.65' }}</h3>
<h3>3.65</h3>
<small>Current GPA</small> <small>Current GPA</small>
</div>
</div> </div>
</div> <div class="col-md-4">
<div class="col-md-4 mb-4">
<div class="summary-card"> <div class="summary-card">
<i class="fas fa-book-open"></i>
<i class="fas fa-book"></i> <h3>{{ $passedModules ?? 0 }} / {{ $totalModules ?? 0 }}</h3>
<h3>6 / 6</h3>
<small>Modules Passed</small> <small>Modules Passed</small>
</div> </div>
</div> </div>
</div> </div>
<!-- Result Table --> <!-- Result Table -->
<div class="result-card"> <div class="result-card">
<div class="table-head d-flex justify-content-between align-items-center">
<div class="table-head"> <h5 class="mb-0 fw-bold">
<h4 class="mb-0">
Semester Results Semester Results
</h5>
</h4> @if(isset($results) && $results->isNotEmpty())
<span class="badge bg-light text-dark">
{{ optional($results->first())->academic_year }} | {{ optional($results->first())->semester }}
</span>
@endif
</div> </div>
<table class="table table-hover"> <div class="table-responsive">
<table class="table table-hover align-middle">
<thead> <thead>
<tr> <tr>
<th>Module Code</th>
<th>Module</th> <th>Module Name</th>
<th>Marks</th> <th>Marks</th>
<th>Grade</th> <th>Grade</th>
<th>Status</th> <th>Status</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@forelse ($results ?? [] as $item)
<tr> <tr>
<td class="fw-bold" style="color: var(--theme-navy);">{{ $item->module_code }}</td>
<td>Engine Technology</td> <td class="fw-semibold">{{ $item->module_name }}</td>
<td>{{ $item->marks }}</td>
<td>91</td>
<td> <td>
@php
$gradeClass = 'b';
$upperGrade = strtoupper($item->grade ?? '');
<span class="grade a"> if(str_contains($upperGrade, 'A')) {
$gradeClass = 'a';
A+ } elseif(str_contains($upperGrade, 'F')) {
$gradeClass = 'fail';
</span> } 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>
<td>Pass</td>
</tr> </tr>
@empty
<tr> <tr>
<td colspan="5" class="text-center py-4 text-muted">
<td>Brake Systems</td> <i class="fas fa-info-circle me-1"></i> No result records found for your account.
<td>84</td>
<td>
<span class="grade a">
A
</span>
</td> </td>
<td>Pass</td>
</tr> </tr>
@endforelse
<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>
</tbody> </tbody>
</table> </table>
</div>
</div>
</div> </div>
<!-- Performance --> <!-- Performance & Download Section (Side by Side) -->
<div class="row g-4 align-items-stretch">
<div class="result-card mt-4">
<!-- Overall Performance Card -->
<div class="col-md-6">
<div class="result-card h-100 mt-0">
<div class="table-head"> <div class="table-head">
<h5 class="mb-0 fw-bold">
<h4 class="mb-0">
Overall Performance Overall Performance
</h5>
</h4>
</div> </div>
<div class="p-4"> <div class="p-4 d-flex flex-column justify-content-center">
<div class="d-flex justify-content-between mb-2">
<p class="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>
Course Completion </div>
</p>
<div class="progress mb-4"> <div class="progress mb-4">
<div class="progress-bar progress-bar-navy" style="width: {{ $averageMarks ?? 0 }}%"></div>
<div class="progress-bar bg-success"
style="width:82%">
</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> </div>
<p class="mb-2">
Attendance Score
</p>
<div class="progress"> <div class="progress">
<div class="progress-bar progress-bar-red" style="width: 90%"></div>
<div class="progress-bar bg-warning" </div>
</div>
style="width:90%"> </div>
</div> </div>
</div> <!-- Download Section Card -->
<div class="col-md-6">
</div> <div class="download-card h-100 mt-0 flex-column justify-content-between align-items-start text-start">
</div>
<!-- Download -->
<div class="download-card">
<div> <div>
<h4 class="mb-3">Download Official Result Sheet</h4>
<h4> <p class="mb-4">
Get your latest semester examination results in official PDF format.
Download Official Result Sheet
</h4>
<p class="mb-0">
Download your latest semester examination results in PDF format.
</p> </p>
</div> </div>
<button class="btn btn-result"> <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
<i class="fas fa-download"></i>
Download PDF
</button> </button>
</div>
</div> </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 @endsection

View File

@ -3,26 +3,51 @@
@section('title', 'Student Login') @section('title', 'Student Login')
@push('styles') @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> <style>
body { :root {
background: #f5f7fb; --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; body {
transform: scale(0.95); background: var(--bg-light);
font-family: 'Poppins', sans-serif;
} }
/* LEFT PANEL */ /* LEFT PANEL */
.left-panel { .left-panel {
min-height: 100vh; min-height: 100vh;
background: #f8f9fa; background: linear-gradient(135deg, var(--theme-navy) 0%, var(--theme-navy-dark) 100%);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
color: var(--white);
border-right: 5px solid var(--theme-red);
} }
.left-panel img { .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 */ /* RIGHT PANEL */
@ -32,106 +57,103 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
padding: 40px; padding: 40px;
background: var(--bg-light);
scale: 0.7;
} }
/* LOGIN BOX */ /* LOGIN BOX */
.box { .box {
width: 100%; width: 100%;
max-width: 500px; max-width: 480px;
background: #ffffff; background: var(--white);
padding: 45px; padding: 45px 40px;
border-radius: 18px; border-radius: 16px;
box-shadow: 0 15px 40px rgba(0,0,0,0.12); box-shadow: 0 10px 30px rgba(31, 37, 65, 0.08);
border: 1px solid #e2e8f0;
} }
/* TITLE */ /* TITLE */
.headline { .headline {
text-align: center; text-align: center;
font-size: 32px; font-size: 28px;
font-weight: 700; font-weight: 700;
color: #222; color: var(--theme-navy);
margin-bottom: 35px; margin-bottom: 35px;
} }
/* INPUT */ /* INPUT CONTAINER */
.input-container { .input-container {
position: relative; position: relative;
margin-bottom: 25px; margin-bottom: 28px;
font-size: 22px;
font-family: arial;
} }
.input-container input { .input-container input {
width: 100%; width: 100%;
height: 50px; height: 48px;
padding: 12px 0; padding: 10px 0 5px 0;
border: none; border: none;
border-bottom: 2px solid #ddd; border-bottom: 2px solid #cbd5e1;
background: transparent; background: transparent;
outline: none; outline: none;
font-size: 22px; font-size: 16px;
font-family: arial; color: #1e293b;
transition: all 0.3s ease;
} }
.input-container label { .input-container label {
position: absolute; position: absolute;
top: 15px; top: 12px;
left: 0; left: 0;
color: #744a68; color: #64748b;
transition: .3s; transition: 0.3s ease;
pointer-events: none; pointer-events: none;
font-size: 22px; font-size: 15px;
font-family: arial;
} }
/* FLOATING LABEL & VALIDATION STATES */ /* FLOATING LABEL & VALIDATION STATES */
.input-container input:focus, .input-container input:focus {
.input-container input:valid { border-bottom-color: var(--theme-navy);
border-bottom-color: #744a68;
font-size: 20px;
font-family: arial;
} }
.input-container input:focus + label, .input-container input:focus + label,
.input-container input:not(:placeholder-shown) + label { .input-container input:not(:placeholder-shown) + label {
top: -12px; top: -12px;
font-size: 12px; font-size: 12px;
color: #744a68; color: var(--theme-navy);
font-weight: 600; font-weight: 600;
} }
/* FORGOT PASSWORD */ /* FORGOT PASSWORD */
.forgot-link { .forgot-link {
color: #744a68; color: var(--theme-red);
font-size: 16px; font-size: 14px;
text-decoration: none; text-decoration: none;
font-weight: 500; font-weight: 500;
padding-left: 37%;
transition: color 0.2s ease-in-out; transition: color 0.2s ease-in-out;
} }
.forgot-link:hover { .forgot-link:hover {
text-decoration: underline; text-decoration: underline;
color: #5E244E; color: var(--theme-red-hover);
} }
/* BUTTON */ /* BUTTON */
.btn-primary { .btn-primary {
height: 50px; height: 48px;
width: 100%; width: 100%;
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
background: #5E244E; background: var(--theme-red) !important;
border: none; border: none;
color: white; color: var(--white) !important;
/* border-radius: 8px; */ border-radius: 8px;
transition: background 0.2s ease-in-out, transform 0.1s ease; transition: all 0.2s ease;
} }
.btn-primary:hover, .btn-primary:focus { .btn-primary:hover, .btn-primary:focus {
background: #4a1c3e; background: #822424 !important;
color: white; box-shadow: 0 4px 12px rgba(130, 36, 36, 0.3);
} }
.btn-primary:active { .btn-primary:active {
@ -141,25 +163,28 @@
/* BOTTOM TEXT */ /* BOTTOM TEXT */
.dontacc { .dontacc {
text-align: center; text-align: center;
margin-top: 15px;
} }
.dontacc p { .dontacc p {
color: #666; color: #64748b;
font-size: 14px;
} }
.dontacc a { .dontacc a {
color: #744a68; color: var(--theme-navy);
text-decoration: none; text-decoration: none;
font-weight: 600; font-weight: 600;
font-size: 16px; font-size: 15px;
font-family: arial; transition: color 0.2s ease;
} }
.dontacc a:hover { .dontacc a:hover {
text-decoration: underline; text-decoration: underline;
color: var(--theme-navy-dark);
} }
/* RESPONSIVE DESIGN */
@media(max-width:991px) { @media(max-width:991px) {
.left-panel { .left-panel {
display: none !important; display: none !important;
@ -171,16 +196,38 @@
} }
.box { .box {
padding: 30px; padding: 35px 25px;
} }
.headline { .headline {
font-size: 28px; font-size: 24px;
color: #5E244E;
font-weight: bold;
font-family: Arial;
} }
} }
.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> </style>
@endpush @endpush
@ -188,17 +235,9 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="row min-vh-100"> <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"> <div class="box">
<h2 class="headline">Student Sign In</h2> <h2 class="headline">Student Sign In</h2>
@ -213,9 +252,18 @@
@enderror @enderror
</div> </div>
<div class="input-container"> <!-- <div class="input-container">
<input type="password" name="password" placeholder=" " required> <input type="password" name="password" placeholder=" " required>
<label>Password</label> <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') @error('password')
<span class="d-block text-danger mt-1 small">{{ $message }}</span> <span class="d-block text-danger mt-1 small">{{ $message }}</span>
@enderror @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 Sign In
</button> </button>
<div class="d-flex justify-content-end mb-4">
<div class="d-flex justify-content-end mb-4" style="gap: 10px;padding-top: 10px; padding-left: 190px;">
<a href="{{ url('/password/reset') }}" class="forgot-link">Forgot Password?</a> <a href="{{ url('/password/reset') }}" class="forgot-link">Forgot Password?</a>
</div> </div>
<div class="dontacc" style="padding-top: 10px; " > <div class="dontacc">
<!-- <p class="mb-1">Don't have an account?</p> --> <!-- <p class="mb-1">Don't have an account?</p> -->
<a href="{{ url('/signup') }}">Create Student Account</a> <a href="{{ url('/signup') }}">Create Student Account</a>
</div> </div>
@ -243,3 +290,19 @@
</div> </div>
</div> </div>
@endsection @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>

View File

@ -3,6 +3,9 @@
@section('title', 'Student Registration') @section('title', 'Student Registration')
@push('styles') @push('styles')
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style> <style>
body { body {
background: #f5f7fb; background: #f5f7fb;
@ -10,7 +13,7 @@
scale: 0.92; scale: 0.92;
} }
/* LEFT PANEL (If active) */
.left-panel { .left-panel {
background: #5E244E; background: #5E244E;
color: white; color: white;
@ -20,7 +23,6 @@
padding: 40px; padding: 40px;
} }
/* RIGHT PANEL */
.right-panel { .right-panel {
min-height: 100vh; min-height: 100vh;
display: flex; display: flex;
@ -37,9 +39,9 @@
padding: 45px; padding: 45px;
border-radius: 18px; border-radius: 18px;
box-shadow: 0 15px 40px rgba(0,0,0,0.12); box-shadow: 0 15px 40px rgba(0,0,0,0.12);
scale : 0.72
} }
/* TITLE */
.headline { .headline {
text-align: center; text-align: center;
font-size: 32px; font-size: 32px;
@ -48,7 +50,7 @@
margin-bottom: 35px; margin-bottom: 35px;
} }
/* MODERN INPUT WITH FLOATING LABELS */
.input-container { .input-container {
position: relative; position: relative;
margin-bottom: 25px; margin-bottom: 25px;
@ -57,7 +59,7 @@
.input-container input { .input-container input {
width: 100%; width: 100%;
height: 50px; height: 50px;
padding: 15px 0 5px 0; padding: 15px 35px 5px 0;
border: none; border: none;
border-bottom: 2px solid #ddd; border-bottom: 2px solid #ddd;
background: transparent; background: transparent;
@ -77,12 +79,12 @@
font-size: 16px; font-size: 16px;
} }
/* Input Focus States */
.input-container input:focus { .input-container input:focus {
border-bottom-color: #744a68; border-bottom-color: #744a68;
} }
/* Label Floating Effect */
.input-container input:focus + label, .input-container input:focus + label,
.input-container input:not(:placeholder-shown) + label { .input-container input:not(:placeholder-shown) + label {
top: -10px; top: -10px;
@ -91,6 +93,22 @@
font-weight: 600; 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 */ /* CHECKBOX STYLE */
.form-check-input:checked { .form-check-input:checked {
background-color: #5E244E; background-color: #5E244E;
@ -109,14 +127,14 @@
width: 100%; width: 100%;
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
background: #5E244E; background: #822424;
border: none; border: none;
color: white; color: white;
transition: background 0.2s ease-in-out, transform 0.1s ease; transition: background 0.2s ease-in-out, transform 0.1s ease;
} }
.btn-primary:hover, .btn-primary:focus { .btn-primary:hover, .btn-primary:focus {
background: #4a1c3e; background: #822424;
color: white; color: white;
} }
@ -124,7 +142,7 @@
transform: scale(0.98); transform: scale(0.98);
} }
/* BOTTOM TEXT */
.dontacc { .dontacc {
text-align: center; text-align: center;
} }
@ -147,6 +165,37 @@
color: #5E244E; 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) { @media(max-width:991px) {
.right-panel { .right-panel {
min-height: 100vh; min-height: 100vh;
@ -170,11 +219,12 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="row min-vh-100"> <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"> <div class="box">
<h2 class="headline">Student Registration</h2> <h2 class="headline">Student Registration</h2>
<form method="POST" action="{{ url('/signuppage') }}"> <form method="POST" action="{{ url('/signuppage') }}">
@csrf @csrf
<div class="input-container"> <div class="input-container">
@ -209,19 +259,38 @@
@enderror @enderror
</div> </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> <label>Password</label>
<i class="fa-solid fa-eye toggle-password" id="togglePassword"></i>
@error('password') @error('password')
<span class="d-block text-danger mt-1 small">{{ $message }}</span> <span class="d-block text-danger mt-1 small">{{ $message }}</span>
@enderror @enderror
</div> </div>
<div class="input-container">
<input type="password" name="password_confirmation" placeholder=" " required autocomplete="new-password"> <div class="password-rules" id="passwordRules">
<label>Confirm Password</label> <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>
<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"> <div class="form-check mb-4 d-flex align-items-center gap-2">
<input class="form-check-input" type="checkbox" id="agree" required> <input class="form-check-input" type="checkbox" id="agree" required>
<label class="form-check-label" for="agree"> <label class="form-check-label" for="agree">
@ -244,3 +313,96 @@
</div> </div>
</div> </div>
@endsection @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

View File

@ -4,382 +4,539 @@
@section('content') @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> <style>
body{ :root {
font-family:'Poppins',sans-serif; --theme-navy: #1E233E;
background:#f4f7fc; --theme-navy-dark: #15182C;
--theme-red: #822424;
--theme-red-hover: #df2c3e;
--theme-yellow: #FFEA85;
--theme-bg: #F4F6F9;
--text-dark: #1E293B;
} }
.page-header{ /* Page Header Hero */
background:linear-gradient(135deg,#9954b8,#4f3d5b)); .timetable-hero {
color:#fff; background: linear-gradient(135deg, #1E233E 0%, #2A1F3B 50%, #4A1A24 100%);
padding:45px;
border-radius: 20px; border-radius: 20px;
background-color: #5E244E; padding: 32px 38px;
margin-bottom:30px; margin-bottom: 28px;
} box-shadow: 0 12px 32px rgba(30, 35, 62, 0.16);
position: relative;
.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);
overflow: hidden; overflow: hidden;
} }
.table thead{ .timetable-hero::before {
background:#0d6efd; content: '';
color:#fff; 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, .btn-print {
.table th{ background: #ffffff;
text-align:center; color: #1E233E;
vertical-align:middle; font-weight: 700;
min-width:140px; 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{ .btn-print:hover {
background:#0d6efd; background: var(--theme-yellow);
color: #1E233E;
transform: translateY(-2px);
box-shadow: 0 10px 24px rgba(255, 234, 133, 0.4);
} }
.badge-practical{ /* Top Cards */
background:#198754; .top-info-card {
} background: #ffffff;
border: 1px solid #E2E8F0;
.badge-workshop{ border-radius: 20px;
background:#fd7e14; padding: 26px;
} box-shadow: 0 4px 20px rgba(0, 0, 0, 0.03);
.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;
height: 100%; height: 100%;
} }
.today-card h5{ .card-title-heading {
font-weight:600; 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; 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){ .legend-pill.theory {
background: linear-gradient(135deg, #EFF6FF 0%, #DBEAFE 100%);
.table td, color: #1E40AF;
.table th{ border: 1px solid #BFDBFE;
font-size:13px;
min-width:120px;
} }
.page-header{ .legend-pill.practical {
padding:25px; 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> </style>
<div class="container py-4"> <div class="portal-content-container">
<!-- Header --> <!-- Hero Header -->
<div class="timetable-hero d-flex align-items-center justify-content-between flex-wrap gap-3">
<div class="page-header"> <div class="position-relative" style="z-index: 1;">
<div class="d-flex align-items-center gap-2 mb-2">
<div class="d-flex justify-content-between align-items-center flex-wrap"> <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
<div> </span>
</div>
<h2><i class="fas fa-calendar-alt me-2"></i>My Class Timetable</h2> <h2 class="fw-bold text-white mb-1" style="letter-spacing: -0.5px;">
My Class Timetable
<p class="mb-0"> </h2>
Automobile Engineering Academy Student Portal <p class="text-white-50 mb-0 fs-6">
Automobile Engineering Academy Student Academic Schedule 2026
</p> </p>
</div> </div>
<button class="btn btn-light download-btn" onclick="window.print()"> <button class="btn btn-print shadow-sm" onclick="window.print()">
<i class="fas fa-print me-2"></i>Print <i class="fa-solid fa-print me-2"></i>Print Timetable
</button> </button>
</div> </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>
<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> <div>
Today's Schedule
<strong>01:30 - 03:30</strong><br> <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 class="badge badge-practical">
Practical
</span> </span>
</div>
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="today-class-item {{ $typeClass }}">
<div class="d-flex align-items-center justify-content-between mb-1">
<div class="col-lg-8"> <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">
<div class="info-card p-4 h-100"> <i class="fa-solid {{ $iconClass }}"></i> {{ $todayItem->type }}
<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>
</span> </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> <!-- Timetable Legend & Guidelines Card -->
<span class="badge badge-practical">Practical</span> <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="legend-pill practical">
<span> <i class="fa-solid fa-flask"></i> Practical Session
<span class="badge badge-workshop">Workshop</span>
</span> </span>
<span class="legend-pill workshop">
<span> <i class="fa-solid fa-screwdriver-wrench"></i> Workshop Training
<span class="badge badge-break">Break</span>
</span> </span>
<span class="legend-pill break">
<i class="fa-solid fa-utensils"></i> Rest / Lunch Break
</span>
</div>
</div> </div>
<hr> <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">
<p class="mb-0 text-muted"> <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;">
Please arrive at least 15 minutes before each class. <i class="fa-solid fa-exclamation" style="font-size: 14px;"></i>
Attendance is compulsory for all practical sessions. </div>
</p> <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> </div>
</div> <!-- Main Timetable Grid -->
<div class="timetable-wrapper mb-5">
<!-- Timetable -->
<div class="table-card">
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-modern align-middle mb-0">
<table class="table table-bordered align-middle mb-0">
<thead> <thead>
<tr> <tr>
<th style="width: 150px;">
<th>Time</th> <i class="fa-regular fa-clock me-1"></i> Time
</th>
<th>Monday</th> @foreach($days as $day)
@php
<th>Tuesday</th> $isToday = ($todayName ?? '') == $day;
@endphp
<th>Wednesday</th> <th class="{{ $isToday ? 'today-header' : '' }}">
{{ $day }}
<th>Thursday</th> @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);">
<th>Friday</th> <i class="fa-solid fa-star me-1"></i>TODAY
</span>
@endif
</th>
@endforeach
</tr> </tr>
</thead> </thead>
<tbody> <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> <tr>
<th class="time-column">
<th>08:30 - 10:30</th> <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>
<td> <span>{{ $slot }}</span>
<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>
</div> </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>
</div> </div>

File diff suppressed because it is too large Load Diff

View File

@ -6,73 +6,198 @@ use App\Http\Controllers\StudentPortalController;
use App\Http\Controllers\ContactMsgController; use App\Http\Controllers\ContactMsgController;
use App\Http\Controllers\FeedbackController; use App\Http\Controllers\FeedbackController;
use App\Http\Controllers\studentportalnavController; 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('/', [welcomeController::class, 'index'])->name('welcome');
Route::get('/', function () { Route::get('/courses', [coursesController::class, 'index'])->name('courses.index');
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::view('/students', 'students')->name('students'); Route::view('/students', 'students')->name('students');
Route::view('/abouts', 'abouts')->name('abouts'); Route::view('/abouts', 'abouts')->name('abouts');
Route::view('/contact', 'contacts')->name('contact'); Route::view('/contact', 'contacts')->name('contact');
Route::view('/signin', 'signin')->name('signin'); 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'); Route::view('/signup', 'signup')->name('signup');
//student protal /*
Route::view('/Dashboard','StudentPortal')->name('Dashboard'); |--------------------------------------------------------------------------
Route::view('/mycourse', 'mycourse')->name('mycourse'); | System Auth & Contact Routes (POST)
Route::view('/timetable','timetable')->name('timetable'); |--------------------------------------------------------------------------
Route::view('/Assignments','Assignments')->name('Assignments'); */
Route::view('/Studentguidelines','Studentguidelines')->name('Studentguidelines'); Route::post('/signuppage', [AuthController::class, 'register']);
Route::view('/results','results')->name('results'); Route::post('/signin', [AuthController::class, 'login']);
Route::view('/Feedback&Complain','Feedback&Complain')->name('Feedback&Complain'); Route::post('/custom-logout', [AuthController::class, 'logout']);
Route::view('/StudentProfile','StudentProfile')->name('StudentProfile'); 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');
});
});