set courese backend

This commit is contained in:
imadhigp 2026-07-28 16:46:11 +05:30
parent fa299bcd7c
commit d63e9c0a2b
10 changed files with 347 additions and 145 deletions

View File

@ -2,9 +2,60 @@
namespace App\Http\Controllers;
use App\Models\Application;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class applyController extends Controller
class ApplyController extends Controller
{
//
}
public function index()
{
return view('apply'); // Tawa name ekak nam view name eka wenas karanna
}
public function store(Request $request)
{
// 1. Data Validation Rules
$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',
]);
// 2. Multi File Upload Process
$certificatePaths = [];
if ($request->hasFile('certificates')) {
foreach ($request->file('certificates') as $file) {
$path = $file->store('certificates', 'public');
$certificatePaths[] = $path;
}
}
// 3. Current Logged-in User ID එක set කිරීම & Data Save කිරීම
$application = new Application($validatedData);
$application->user_id = Auth::id(); // Log unukena ge ID eka attach wei
$application->certificates = $certificatePaths; // Paths array eka save wei
$application->save();
return redirect()->back()->with('success', 'Your application has been submitted successfully!');
}
}

View File

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

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

@ -2,9 +2,29 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class courses extends Model
{
//
}
use HasFactory;
protected $table = 'courses';
protected $fillable = [
'title',
'image',
'duration',
'level',
'author',
'desc',
'student',
'rating',
'badge',
'trending',
'course_code',
'status'
];
}

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

@ -212,7 +212,7 @@ body {
We focus on building skilled professionals who are ready for
the global automotive industry.
</p>
<a href="{{ route('courses') }}" class="btn btn-view-courses btn-lg px-4 rounded-pill shadow-sm">
<a href="/courses" class="btn btn-view-courses btn-lg px-4 rounded-pill shadow-sm">
View Courses@extends('layouts.app')
@section('title','About Us')
@ -418,7 +418,7 @@ body {
We focus on building skilled professionals who are ready for
the global automotive industry.
</p>
<a href="{{ route('courses') }}" class="btn btn-view-courses btn-lg px-4 rounded-pill shadow-sm">
<a href="/courses" class="btn btn-view-courses btn-lg px-4 rounded-pill shadow-sm">
View Courses
</a>
</div>

View File

@ -166,7 +166,24 @@
</div>
<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
{{-- STUDENT INFORMATION --}}

View File

@ -6,23 +6,22 @@
<style>
:root {
/* Premium Modern Automotive Palette (Updated based on your custom inputs) */
--primary: #3E51B8; /* Tech Blue / Main Brand Color */
--primary-light: #0a67df; /* Vibrant Electric Blue */
--secondary: #BC1A1A; /* Deep Racing Red */
--secondary-hover: #822424; /* Dark Burnt Red */
--accent-dark: #753939; /* Muted Crimson */
--accent-light: rgba(227, 100, 20, 0.1); /* Soft Amber/Orange tint for badges */
--accent-orange: #e36414; /* Warning/Industrial Orange */
--accent-yellow: #FFE618; /* High-Visibility Electric Yellow */
--bg-light: #F8FAFC; /* Soft slate light gray */
/* Premium Modern Automotive Palette */
--primary: #3E51B8;
--primary-light: #0a67df;
--secondary: #BC1A1A;
--secondary-hover: #822424;
--accent-dark: #753939;
--accent-light: rgba(227, 100, 20, 0.1);
--accent-orange: #e36414;
--accent-yellow: #FFE618;
--bg-light: #F8FAFC;
/* Semantic Adjustments */
--text-main: #1E293B; /* Slate dark grey */
--text-muted: #64748B; /* Neutral gray */
--text-main: #1E293B;
--text-muted: #64748B;
--card-border: rgba(62, 81, 184, 0.1);
--shadow-color: rgba(15, 44, 89, 0.05);
--success-green: #10B981; /* Modern emerald green */
--success-green: #10B981;
}
body {
@ -91,19 +90,15 @@ body {
background: linear-gradient(135deg, var(--secondary) 0%, var(--secondary-hover) 100%);
}
/* ===== HIGHLY SATISFYING HORIZONTAL COURSE CARDS ===== */
/* ===== HORIZONTAL COURSE CARDS ===== */
.course-card {
overflow: hidden;
background: #fff;
transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1);
/* box-shadow: 0 8px 30px var(--shadow-color); */
}
.course-card:hover {
transform: translateY(-6px);
/* box-shadow: 0 20px 40px rgba(62, 81, 184, 0.15); */
/* border-color: var(--primary-light); */
}
.course-image-wrapper {
@ -234,10 +229,9 @@ body {
box-shadow: 0 6px 18px rgba(188, 26, 26, 0.3);
}
/* --- Modernized Why Study With Us Section --- */
/* --- Features Section --- */
.features-section {
background-color: var(--bg-light);
/* border-radius: 32px; */
padding: 80px 40px;
margin-bottom: 40px;
background-image: radial-gradient(rgba(62, 81, 184, 0.04) 1px, transparent 0);
@ -251,14 +245,6 @@ body {
margin-bottom: 54px;
}
.section-divider {
height: 4px;
width: 65px;
background: linear-gradient(90deg, var(--secondary) 0%, var(--accent-yellow) 100%);
margin: 0 auto 45px auto;
border-radius: 10px;
}
.feature-box {
background: #fff;
padding: 40px 28px;
@ -292,7 +278,6 @@ body {
color:#6a2525 ;
}
.feature-box:hover .feature-icon-wrapper {
background: linear-gradient(135deg, var(--secondary) 0%, var(--accent-orange) 100%);
color: #fff;
@ -306,7 +291,6 @@ body {
.feature-box:hover .feature-icon-wrapper i {
transform: rotateY(-180deg);
}
.feature-box h5 {
@ -320,9 +304,6 @@ body {
color: #822424 ;
}
.feature-box p {
font-size: 14.5px;
color: var(--text-muted);
@ -337,9 +318,7 @@ body {
margin-top: 30px;
}
/* ========================================================
Custom Pure CSS Animations (Scroll Animations)
======================================================== */
/* Animations */
.animate-on-scroll {
opacity: 0;
transition: all 0.8s cubic-bezier(0.25, 1, 0.5, 1);
@ -378,77 +357,6 @@ body {
</div>
</section>
@php
$courses=[
[
'image'=>'https://images.unsplash.com/photo-1486262715619-67b85e0b08d3?auto=format&fit=crop&w=900&q=80',
'title'=>'Diploma in Automotive Engineering',
'duration'=>'2 Years',
'level'=>'Diploma',
'author'=>'Automotive Engineering Dept.',
'desc'=>'Master engine diagnostics, modern hybrid vehicle maintenance, and advanced automotive electrical systems with hands-on labs.',
'students'=>'1,240 students enrolled',
'rating'=>'4.9',
'badge'=>'Popular'
],
[
'image'=>'https://images.unsplash.com/photo-1503376780353-7e6692767b70?auto=format&fit=crop&w=900&q=80',
'title'=>'Mechanical Systems Technology',
'duration'=>'18 Months',
'level'=>'Certificate',
'author'=>'Tech & Service Campus',
'desc'=>'Comprehensive training on vehicle suspension, transmissions, steering, braking mechanisms, and professional repair workshop skills.',
'students'=>'850 students enrolled',
'rating'=>'4.7',
'badge'=>'Bestseller'
],
[
'image'=>'https://images.unsplash.com/photo-1502877338535-766e1452684a?auto=format&fit=crop&w=900&q=80',
'title'=>'Electric Vehicle Technology',
'duration'=>'1 Year',
'level'=>'Advanced',
'author'=>'EV Research Institute',
'desc'=>'Dive into the future of mobility. Learn about smart EV battery packs, fast charging infrastructures, and high-voltage safety.',
'students'=>'640 students enrolled',
'rating'=>'4.8',
'badge'=>'New'
],
[
'image'=>'https://images.unsplash.com/photo-1616788494707-ec28f08d05a1?auto=format&fit=crop&w=900&q=80',
'title'=>'Advanced EFI Engine Tuning & Diagnostic',
'duration'=>'6 Months',
'level'=>'Expert',
'author'=>'Performance Tuning Lab',
'desc'=>'Learn professional ECU remapping, electronic fuel injection (EFI) tuning, sensor calibration, and master high-end oscilloscope diagnostics.',
'students'=>'420 students enrolled',
'rating'=>'4.9',
'badge'=>'Hot & New'
],
[
'image'=>'https://images.unsplash.com/photo-1568605117036-5fe5e7bab0b7?auto=format&fit=crop&w=900&q=80',
'title'=>'Hybrid & Plug-in Hybrid Masterclass',
'duration'=>'8 Months',
'level'=>'Professional',
'author'=>'Automotive Engineering Dept.',
'desc'=>'Specialized training in Toyota/Honda Hybrid Synergy Drive systems, inverter repairs, planetary gearboxes, and live diagnostic scanner masterclass.',
'students'=>'980 students enrolled',
'rating'=>'4.8',
'badge'=>'Top Rated'
],
[
'image'=>'https://images.unsplash.com/photo-1517524008697-84bbe3c3fd98?auto=format&fit=crop&w=900&q=80',
'title'=>'Automotive Body Electronics & Comfort Systems',
'duration'=>'1 Year',
'level'=>'Diploma',
'author'=>'Tech & Service Campus',
'desc'=>'Covering modern CAN-bus/LIN-bus communication networks, SRS airbag systems, ABS/ESP braking electronics, and smart climate control.',
'students'=>'510 students enrolled',
'rating'=>'4.6',
'badge'=>'Trending'
],
];
@endphp
<section class="py-5">
<div class="container">
@ -457,35 +365,52 @@ $courses=[
</div>
<div class="row g-4" id="courseContainer">
@foreach($courses as $index => $course)
@forelse($courses as $index => $course)
<div class="col-12 course-item animate-on-scroll fade-up-init" style="transition-delay: {{ $index * 100 }}ms;">
<div class="card course-card h-100">
<div class="row g-0 align-items-center">
{{-- Course Image --}}
<div class="col-md-4">
<div class="course-image-wrapper">
<img src="{{ $course['image'] }}" alt="{{ $course['title'] }}">
<img src="{{ $course->image }}" alt="{{ $course->title }}">
</div>
</div>
{{-- Course Details --}}
<div class="col-md-8">
<div class="card-body">
<h4 class="course-title">{{ $course['title'] }}</h4>
<div class="course-author"><i class="fa-solid fa-user-gear me-1"></i> {{ $course['author'] }}</div>
<h4 class="course-title">{{ $course->title }}</h4>
<p class="course-short-desc">{{ $course['desc'] }}</p>
@if($course->author)
<div class="course-author">
<i class="fa-solid fa-user-gear me-1"></i> {{ $course->author }}
</div>
@endif
<p class="course-short-desc">{{ $course->desc }}</p>
<div class="course-meta-row">
<span class="badge-bestseller">{{ $course['badge'] }}</span>
<span class="rating-star">
<i class="fas fa-star"></i> {{ $course['rating'] }}
</span>
<span class="rating-count">({{ $course['students'] }})</span>
@if($course->badge)
<span class="badge-bestseller">{{ $course->badge }}</span>
@endif
@if($course->rating)
<span class="rating-star">
<i class="fas fa-star"></i> {{ $course->rating }}
</span>
@endif
@if($course->student)
<span class="rating-count">({{ $course->student }} students enrolled)</span>
@endif
</div>
<div class="course-features">
<span><i class="fas fa-tools"></i> Practical Labs</span>
<span><i class="fas fa-certificate"></i> Verified ({{ $course['duration'] }})</span>
<span><i class="fas fa-tools"></i> Level: {{ $course->level ?? 'General' }}</span>
@if($course->duration)
<span><i class="fas fa-certificate"></i> Duration: {{ $course->duration }}</span>
@endif
</div>
<div class="course-footer" style="max-width: 200px;">
@ -497,22 +422,25 @@ $courses=[
</div>
</div>
</div>
@endforeach
@empty
<div class="col-12 text-center py-5">
<h4>No courses available at the moment.</h4>
</div>
@endforelse
</div>
</div>
</section>
{{-- Why Study With Us Section --}}
<section class="pb-5 why-study-section>
<section class="pb-5 why-study-section">
<div class="container">
<<div class="features-section text-center animate-on-scroll fade-up-init"
style="background-image: linear-gradient(rgba(77, 103, 169, 0.61), rgba(0, 0, 0, 0.9)), url('https://images.pexels.com/photos/4489749/pexels-photo-4489749.jpeg?auto=compress&cs=tinysrgb&w=1600');
background-size: cover;
background-position: center;
background-repeat: no-repeat;">
<div class="features-section text-center animate-on-scroll fade-up-init"
style="background-image: linear-gradient(rgba(77, 103, 169, 0.61), rgba(0, 0, 0, 0.9)), url('https://images.pexels.com/photos/4489749/pexels-photo-4489749.jpeg?auto=compress&cs=tinysrgb&w=1600');
background-size: cover;
background-position: center;
background-repeat: no-repeat;">
<h2>Why Study With Us?</h2>
<!-- <div class="section-divider"></div> -->
<div class="row g-4">
<div class="col-xl-3 col-md-6">
@ -569,8 +497,8 @@ document.addEventListener('DOMContentLoaded', function () {
let hasResults = false;
courseItems.forEach(function(item) {
let title = item.querySelector('.course-title').textContent.toLowerCase();
let desc = item.querySelector('.course-short-desc').textContent.toLowerCase();
let title = item.querySelector('.course-title') ? item.querySelector('.course-title').textContent.toLowerCase() : '';
let desc = item.querySelector('.course-short-desc') ? item.querySelector('.course-short-desc').textContent.toLowerCase() : '';
if (title.includes(filter) || desc.includes(filter)) {
item.style.setProperty('display', '', 'important');

View File

@ -529,7 +529,71 @@ body {
</section>
{{-- ===================== COURSE FINDER MODAL ===================== --}}
<div class="modal fade" id="courseFinderModal" tabindex="-1" aria-labelledby="courseFinderModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg modal-dialog-scrollable">
<div class="modal-content border-0 shadow">
<div class="modal-header custom-modal-header text-white">
<h5 class="modal-title fw-bold fs-6 fs-md-5" id="courseFinderModalLabel">
<i class="fa-solid fa-compass me-2"></i>Find Your Course
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body p-3 p-md-4">
<form id="courseFinderForm">
{{-- Qualification Field --}}
<div class="mb-3">
<label for="educationLevel" class="form-label fw-semibold text-dark small fs-6">
<i class="fa-solid fa-user-degree me-1 text-primary"></i> What is your highest educational qualification?
</label>
<select class="form-select form-select-lg border-2 fs-6" id="educationLevel" required>
<option value="" selected disabled>Select Educational Qualification</option>
<option value="ol">Completed Ordinary Level (O/L)</option>
<option value="al">Completed Advanced Level (A/L)</option>
<option value="diploma">Diploma / Vocational Qualification</option>
</select>
</div>
{{-- Interest Area Field --}}
<div class="mb-4">
<label for="interestArea" class="form-label fw-semibold text-dark small fs-6">
<i class="fa-solid fa-car-battery me-1 text-primary"></i> Which area of Automotive Engineering interests you most?
</label>
<select class="form-select form-select-lg border-2 fs-6" id="interestArea" required>
<option value="" selected disabled>Select Field of Interest</option>
<option value="mechanical">Automotive Mechanical & Diagnostics</option>
<option value="ev">Electric Vehicles (EV) & Battery Technology</option>
<option value="all">General Automotive Engineering (All Areas)</option>
</select>
</div>
{{-- Submit Button --}}
<button type="submit" class="btn btn-theme w-100 py-2.5 fw-bold text-white shadow-sm" style="background:#822424;">
<i class="fa-solid fa-magnifying-glass me-2"></i>Find Recommended Courses
</button>
</form>
{{-- Result Area --}}
<div id="recommendedResults" class="mt-4" style="display: none;">
<hr class="my-3 my-md-4">
<h5 class="fw-bold text-success mb-3 fs-6 fs-md-5">
<i class="fa-solid fa-circle-check me-2"></i>Recommended Courses for You:
</h5>
<div id="resultsContainer" class="row g-3">
<!-- JS injected courses will appear here -->
</div>
</div>
</div>
</div>
</div>
</div>
<!-- <div class="modal fade" id="courseFinderModal" tabindex="-1" aria-labelledby="courseFinderModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content" style="width:60%;">
<div class="modal-header custom-modal-header">
@ -567,22 +631,22 @@ body {
<button type="submit" class="btn btn-theme w-100" style="background:#822424;">
<i class="fa-solid fa-magnifying-glass me-2"></i>Find Recommended Courses
</button>
</form>
</form> -->
{{-- Result Area --}}
<div id="recommendedResults" class="mt-4" style="display: none;">
<!-- <div id="recommendedResults" class="mt-4" style="display: none;">
<hr class="my-4">
<h5 class="fw-bold text-success mb-3">
<i class="fa-solid fa-circle-check me-2"></i>Recommended Courses for You:
</h5>
<div id="resultsContainer" class="row g-3">
<!-- JS injected courses will appear here -->
</div>
</div>
</div>
</div>
</div>
</div>
</div> -->
<script>
document.addEventListener('DOMContentLoaded', function () {

View File

@ -8,6 +8,8 @@ use App\Http\Controllers\FeedbackController;
use App\Http\Controllers\studentportalnavController;
use App\Http\Controllers\auth\asswordController;
use App\Http\Controllers\Auth\ForgotPasswordController;
use App\Http\Controllers\coursesController;
use App\Http\Controllers\ApplyController;
/*
@ -21,7 +23,13 @@ Route::get('/', function () {
return view('welcome');
});
Route::get('/courses', [coursesController::class, 'index'])->name('courses.index');
Route::middleware(['auth'])->group(function () {
Route::get('/apply', [ApplyController::class, 'index'])->name('apply.index');
Route::post('/apply', [ApplyController::class, 'store'])->name('apply.store');
});
Route::middleware('guest')->group(function () {
@ -83,7 +91,7 @@ Route::get('/student-portal', function () {
Route::view('/apply', 'apply')->name('apply');
Route::view('/courses', 'courses')->name('courses');
// Route::view('/courses', 'courses')->name('courses');
Route::view('/students', 'students')->name('students');
Route::view('/abouts', 'abouts')->name('abouts');
Route::view('/contact', 'contacts')->name('contact');