Add cost calculator page and update header link

- Created a new cost calculator page with form functionality to select study options.
- Updated the header to link to the new cost calculator route instead of a static PHP file.
This commit is contained in:
2025-08-12 17:59:36 +05:45
parent 59e5392370
commit 03c5955768
18 changed files with 778 additions and 514 deletions

View File

@@ -9,7 +9,8 @@ use Modules\CourseFinder\Http\Controllers\ProgramLevelController;
Route::get('/', [WebsiteController::class, 'home']); Route::get('/', [WebsiteController::class, 'home']);
Route::get('course-finder/{id}', [WebsiteController::class, 'coursefinderSingle'])->name('coursefinder.single'); Route::get('course-finder/{id}', [WebsiteController::class, 'coursefinderSingle'])->name('coursefinder.single');
Route::get('/course-finder', [WebsiteController::class, 'coursefinder'])->name('program.coursefinder'); Route::get('/course-finder/', [WebsiteController::class, 'coursefinder'])->name('program.coursefinder');
Route::get('/cost-calculator', [WebsiteController::class, 'costCalculator'])->name('cost.calculator');
Route::get('/resources', [WebsiteController::class, 'resources'])->name('resources'); Route::get('/resources', [WebsiteController::class, 'resources'])->name('resources');
Route::get('blog/{alias}', [WebsiteController::class, 'blogSingle'])->name('blog.single'); Route::get('blog/{alias}', [WebsiteController::class, 'blogSingle'])->name('blog.single');
Route::get('service/{alias}', [WebsiteController::class, 'serviceSingle'])->name('service.single'); Route::get('service/{alias}', [WebsiteController::class, 'serviceSingle'])->name('service.single');

View File

@@ -239,4 +239,17 @@ class WebsiteController extends Controller
return view("client.raffles.pages.resources-template", $data); return view("client.raffles.pages.resources-template", $data);
} }
public function costCalculator(Request $request)
{
$data['programs'] = $this->programService->findAll($request);
$data['countryOptions'] = Country::where('status', 1)->where('parent_id', null)->pluck('title', 'id');
$data['programLevelOptions'] = ProgramLevel::where('status', 1)->pluck('title', 'id');
$data['intakeOptions'] = Program::INTAKE;
$data['coopOptions'] = Coop::where('status', 1)->pluck('title', 'id');
$data['testOptions'] = Test::where('status', 1)->where('parent_id', null)->pluck('title', 'id');
$data['statusOptions'] = config('constants.page_status_options');
return view("client.raffles.pages.cost-calculator", $data);
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 KiB

View File

@@ -28,16 +28,16 @@ document.addEventListener("DOMContentLoaded", function () {
} }
}); });
}); });
// university image animation // university image animation
window.addEventListener('DOMContentLoaded', () => { window.addEventListener('DOMContentLoaded', () => {
const section = document.getElementById('animated-section'); const section = document.getElementById('animated-section');
const leftItems = document.querySelectorAll('.left-group .line-item'); const leftItems = document.querySelectorAll('.left-group .line-item');
const rightItems = document.querySelectorAll('.right-group .line-item'); const rightItems = document.querySelectorAll('.right-group .line-item');
const observer = new IntersectionObserver((entries) => { const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => { entries.forEach(entry => {
if (entry.isIntersecting) { if (entry.isIntersecting) {
leftItems.forEach((item, i) => { leftItems.forEach((item, i) => {
@@ -51,16 +51,16 @@ const observer = new IntersectionObserver((entries) => {
rightItems.forEach(item => item.classList.remove('visible')); rightItems.forEach(item => item.classList.remove('visible'));
} }
}); });
}, { threshold: 0.5 }); }, { threshold: 0.5 });
observer.observe(section); observer.observe(section);
}); });
// tabs in free resources // tabs in free resources
function showTab(id) { function showTab(id) {
// Remove active class from all buttons // Remove active class from all buttons
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active')); document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
@@ -69,10 +69,10 @@ observer.observe(section);
// Show the selected tab // Show the selected tab
document.getElementById(id).classList.add('active'); document.getElementById(id).classList.add('active');
} }
// NEW: Attach click event on all tab buttons // NEW: Attach click event on all tab buttons
document.querySelectorAll('.tab-btn').forEach(button => { document.querySelectorAll('.tab-btn').forEach(button => {
button.addEventListener('click', function () { button.addEventListener('click', function () {
// Remove active from all // Remove active from all
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active')); document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
@@ -80,14 +80,14 @@ observer.observe(section);
// Add active to clicked button // Add active to clicked button
this.classList.add('active'); this.classList.add('active');
}); });
}); });
// counter section // counter section
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
const counters = document.querySelectorAll(".counter"); const counters = document.querySelectorAll(".counter");
const observer = new IntersectionObserver(entries => { const observer = new IntersectionObserver(entries => {
@@ -130,11 +130,11 @@ observer.observe(section);
function resetCounter(counter) { function resetCounter(counter) {
counter.textContent = 0; counter.textContent = 0;
} }
}); });
// course finder ball bouncing // course finder ball bouncing
window.addEventListener('DOMContentLoaded', () => { window.addEventListener('DOMContentLoaded', () => {
const canvas = document.getElementById('flagCanvas'); const canvas = document.getElementById('flagCanvas');
const ctx = canvas.getContext('2d'); const ctx = canvas.getContext('2d');
const ballSection = document.getElementById('ball-section'); const ballSection = document.getElementById('ball-section');
@@ -367,8 +367,8 @@ observer.observe(section);
// scroll detect in slider // scroll detect in slider
// JS script // JS script
// JS for updating label on scroll // JS for updating label on scroll
window.addEventListener('load', () => { window.addEventListener('load', () => {
console.log("Window loaded. Running scroll indicator script."); console.log("Window loaded. Running scroll indicator script.");
@@ -450,7 +450,7 @@ if (window.innerWidth < 600) {
// desktop // desktop
vx = 3; vx = 3;
} }
// horizontal speed // horizontal speed
let direction = 1; // 1 = right, -1 = left let direction = 1; // 1 = right, -1 = left
// const amplitude = 150; // const amplitude = 150;
let amplitude; let amplitude;
@@ -532,7 +532,7 @@ function updatePosition() {
requestAnimationFrame(updatePosition); requestAnimationFrame(updatePosition);
} }
document.addEventListener("mousemove", function(e) { document.addEventListener("mousemove", function (e) {
const viewportOffset = plane.getBoundingClientRect(); const viewportOffset = plane.getBoundingClientRect();
const planeCenterX = viewportOffset.left + plane.width / 2; const planeCenterX = viewportOffset.left + plane.width / 2;
const planeCenterY = viewportOffset.top + plane.height / 2; const planeCenterY = viewportOffset.top + plane.height / 2;
@@ -586,47 +586,47 @@ document.addEventListener('keydown', e => {
// cost calculator progress // cost calculator progress
let currentStep = 1; let currentStep = 1;
const totalSteps = 5; const totalSteps = 5;
const monkey = document.getElementById('monkey').querySelector('img'); const monkey = document.getElementById('monkey').querySelector('img');
const monkeyContainer = document.getElementById('monkey'); const monkeyContainer = document.getElementById('monkey');
const nextBtn = document.querySelector('.next-btn button'); const nextBtn = document.querySelector('.next-btn button');
const bananalast = document.getElementById('b5'); const bananalast = document.getElementById('b5');
const monkeyImages = [ const monkeyImages = [
"assets/images/icons/monkey1.png", "/raffles/assets/images/icons/monkey1.png",
"assets/images/icons/monkey2.png", "/raffles/assets/images/icons/monkey2.png",
"assets/images/icons/monkey3.png", "/raffles/assets/images/icons/monkey3.png",
"assets/images/icons/monkey4.png", "/raffles/assets/images/icons/monkey4.png",
"assets/images/icons/monkey5.png", "/raffles/assets/images/icons/monkey5.png",
"assets/images/icons/monkey6.png", "/raffles/assets/images/icons/monkey6.png",
"assets/images/icons/monkey7.png", "/raffles/assets/images/icons/monkey7.png"
]; ];
nextBtn.addEventListener('click', () => { nextBtn.addEventListener('click', () => {
if (currentStep < totalSteps) { if (currentStep < totalSteps) {
currentStep++; currentStep++;
// Move monkey // Move monkey
if (window.innerWidth <= 540) { if (window.innerWidth <= 540) {
const percent = ((currentStep -1) / (totalSteps - 0.2)) * 100; const percent = ((currentStep - 1) / (totalSteps - 0.2)) * 100;
monkeyContainer.style.left = percent + '%'; monkeyContainer.style.left = percent + '%';
} }
else if (window.innerWidth <= 768) { else if (window.innerWidth <= 768) {
const percent = ((currentStep -1) / (totalSteps - 0.3)) * 100; const percent = ((currentStep - 1) / (totalSteps - 0.3)) * 100;
monkeyContainer.style.left = percent + '%'; monkeyContainer.style.left = percent + '%';
} }
else if (window.innerWidth <= 992) { else if (window.innerWidth <= 992) {
const percent = ((currentStep -1) / (totalSteps - 0.7)) * 100; const percent = ((currentStep - 1) / (totalSteps - 0.7)) * 100;
monkeyContainer.style.left = percent + '%'; monkeyContainer.style.left = percent + '%';
} }
else if (window.innerWidth <= 1180) { else if (window.innerWidth <= 1180) {
const percent = ((currentStep -1) / (totalSteps - 0.2)) * 100; const percent = ((currentStep - 1) / (totalSteps - 0.2)) * 100;
monkeyContainer.style.left = percent + '%'; monkeyContainer.style.left = percent + '%';
} }
else{ else {
const percent = ((currentStep -1) / (totalSteps - 0.5)) * 100; const percent = ((currentStep - 1) / (totalSteps - 0.5)) * 100;
monkeyContainer.style.left = percent + '%'; monkeyContainer.style.left = percent + '%';
} }
@@ -647,7 +647,7 @@ document.addEventListener('keydown', e => {
nextBtn.style.display = 'none'; nextBtn.style.display = 'none';
doneBtn.style.display = 'block'; doneBtn.style.display = 'block';
} }
}w } w
}); });
doneBtn.addEventListener('click', () => { doneBtn.addEventListener('click', () => {
bananalast.classList.add('active'); bananalast.classList.add('active');
@@ -665,7 +665,7 @@ doneBtn.addEventListener('click', () => {
} }
}); });
// Final monkey image // Final monkey image

View File

@@ -166,7 +166,7 @@
class="lqd-scrl-indc-el inline-block absolute rounded-4"></span></span></span></a> class="lqd-scrl-indc-el inline-block absolute rounded-4"></span></span></span></a>
</div> </div>
<div class="pl-20 -rotate-90"> <div class="pl-20 -rotate-90">
<a href="cost-calculator.php" <a href="{{ route('cost.calculator') }}"
class="btn btn-solid btn-icon-right rounded-full pointer-events-auto text-white bg-primary module-btn-circle" class="btn btn-solid btn-icon-right rounded-full pointer-events-auto text-white bg-primary module-btn-circle"
data-lqd-interactive-color="true"><span class="btn-icon rotate-90"><i data-lqd-interactive-color="true"><span class="btn-icon rotate-90"><i
class="fas fa-calculator text-20"></i></span></a> class="fas fa-calculator text-20"></i></span></a>

View File

@@ -0,0 +1,250 @@
@extends('client.raffles.layouts.app')
@section('content')
<section class="about section-fall" id="ball-section">
<canvas id="flagCanvas"></canvas>
<div class="study-destinations-banner">
<img src="{{ asset('raffles/assets/images/backgrounds_general/cost-calc.png') }}" alt="">
</div>
<section class="section ">
<div class="flex flex-col gap-5 justify-center items-center text-center">
<h2 class="text-60 md:text-30 text-sec">Cost Calculator</h2>
<div class="title-line mx-auto"></div>
</div>
</section>
<section class="lqd-section pb-160">
<div class="container">
<div class="row" id="interactiveSection">
<div class="col col-lg-7">
<form id="costForm" action="{{ route('cost.calculator') }}" method="POST">
@csrf
<input type="hidden" name="country_id" id="country_id">
<input type="hidden" name="test_id" id="test_id">
<input type="hidden" name="intake_id" id="intake_id">
<input type="hidden" name="programlevel_id" id="programlevel_id">
<div class="cost-choosing">
<div class="step-content active" id="step1">
<h3 class="text-20 text-black font-bold pb-20">Choose items to find the total cost</h3>
<h5 class="text-ter text-18 font-medium pb-20">Where do you want to study?</h5>
<div class="row flex py-20">
@foreach ($countryOptions as $id => $country)
<div class="col col-sm-4">
<div class="flex items-center gap-10 px-10 py-20 bg-white rounded-30 tabs">
<div class="circle1"></div>
<a href="#" class="select-country" data-id="{{ $id }}">
<h3 class="text-20 text-ter p-0 m-0">{{ $country }}</h3>
</a>
</div>
</div>
@endforeach
</div>
</div>
<div class="step-content" id="step2">
<h3 class="text-20 text-black font-bold pb-20">Choose items to find the total cost</h3>
<h5 class="text-ter text-18 font-medium pb-20">Which English Proficiency Do you Have?
</h5>
<div class="row flex py-20">
@foreach ($testOptions as $id => $test)
<div class="col col-sm-4">
<div class="flex items-center gap-10 px-10 py-20 bg-white rounded-30 tabs">
<div class="circle1"></div>
<a href="#" class="select-test" data-id="{{ $id }}">
<h3 class="text-20 text-ter p-0 m-0">{{ $test }}</h3>
</a>
</div>
</div>
@endforeach
</div>
</div>
<div class="step-content" id="step3">
<h3 class="text-20 text-black font-bold pb-20">Choose items to find the total cost</h3>
<h5 class="text-ter text-18 font-medium pb-20">Which Intake do you want to go?</h5>
<div class="row flex py-20">
@foreach ($intakeOptions as $id => $intake)
<div class="col col-sm-4">
<div class="flex items-center gap-10 px-10 py-20 bg-white rounded-30 tabs">
<div class="circle1"></div>
<a href="#" class="select-intake" data-id="{{ $id }}">
<h3 class="text-20 text-ter p-0 m-0">{{ $intake }}</h3>
</a>
</div>
</div>
@endforeach
</div>
</div>
<div class="step-content" id="step4">
<h3 class="text-20 text-black font-bold pb-20">Choose items to find the total cost</h3>
<h5 class="text-ter text-18 font-medium pb-20">How long do you want to study</h5>
<div class="row flex py-20">
<div class="col col-sm-4">
<div class="flex items-center gap-10 px-10 py-20 bg-white rounded-30 tabs">
<div class="circle1"></div>
<a href="#" class="select-year" data-id="1">
<h3 class="text-20 text-ter p-0 m-0">1 year</h3>
</a>
</div>
</div>
<div class="col col-sm-4">
<div class="flex items-center gap-10 px-10 py-20 bg-white rounded-30 tabs">
<div class="circle2"></div>
<a href="#" class="select-year" data-id="2">
<h3 class="text-20 text-ter p-0 m-0">2 year</h3>
</a>
</div>
</div>
<div class="col col-sm-4">
<div class="flex items-center gap-10 px-10 py-10 bg-white rounded-30 tabs">
<div class="circle1"></div>
<a href="#" class="select-year" data-id="3">
<h3 class="text-20 text-ter p-0 m-0">3 year</h3>
</a>
</div>
</div>
</div>
</div>
<div class="step-content" id="step5">
<h3 class="text-20 text-black font-bold pb-20">Choose items to find the total cost</h3>
<h5 class="text-ter text-18 font-medium pb-20">Whats Your Program Level Choice?</h5>
<div class="row flex py-20">
@foreach ($programLevelOptions as $id => $level)
<div class="col col-sm-4">
<div class="flex items-center gap-10 px-10 py-20 bg-white rounded-30 tabs">
<div class="circle1"></div>
<a href="#" class="select-programlevel_id"
data-id="{{ $id }}">
<h3 class="text-20 text-ter p-0 m-0">{{ $level }}</h3>
</a>
</div>
</div>
@endforeach
</div>
</div>
<div class=" flex items-center justify-center next-btn">
<button id="nextBtn"
class="rounded-30 px-20 py-10 text-ter text-16 text-center border-0 flex items-center gap-10 justify-center">
<p class="m-0 p-0">Next</p> <i class="fa-solid fa-chevron-right"></i>
</button>
<button id="doneBtn" type="submit" style="display: none;">Done</button>
</div>
<div class="progress-line">
<div class="progress-track">
<span class="banana" id="b1">
<div class="dot"
style="width:12px;height:12px;background:#999;border-radius:50%;"></div>
</span>
<span class="banana" id="b2">
<div class="dot"
style="width:12px;height:12px;background:#999;border-radius:50%;"></div>
</span>
<span class="banana" id="b3">
<div class="dot"
style="width:12px;height:12px;background:#999;border-radius:50%;"></div>
</span>
<span class="banana" id="b4">
<div class="dot"
style="width:12px;height:12px;background:#999;border-radius:50%;"></div>
</span>
<span class="banana" id="b5"><img
src="{{ asset('raffles/assets/images/icons/bananas.svg') }}"
alt=""></span>
</div>
<div class="monkey" id="monkey" style="left: 0%;"><img
src="{{ asset('raffles/assets/images/icons/monkey.png') }}" alt="">
</div>
</div>
</div>
</form>
</div>
<div class="col col-lg-1"></div>
<div class="col col-lg-4">
<div class="total-cost">
<h4>Total <span class="text-black">Cost</span> </h4>
<table>
<thead>
<tr>
<th class="font-bold">S.N.</th>
<th class="font-bold ">Select</th>
<th class="font-bold ">Max Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Bachelors</td>
<td>$13000/year</td>
</tr>
<tr>
<td>2</td>
<td>Bachelors</td>
<td>$13000/year</td>
</tr>
<tr>
<td>3</td>
<td>Bachelors</td>
<td>$13000/year</td>
</tr>
<tr>
<td>4</td>
<td>Bachelors</td>
<td>$13000/year</td>
</tr>
<tr>
<td>5</td>
<td>Bachelors</td>
<td>$13000/year</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
</section>
@endsection
@push('js')
<script>
$(document).ready(function() {
const map = {
'select-country': 'country_id',
'select-test': 'test_id',
'select-intake': 'intake_id',
'select-programlevel_id': 'programlevel_id'
};
$(document).on('click', 'a', function(e) {
const classes = $(this).attr('class')?.split(/\s+/) || [];
for (const cls of classes) {
if (map[cls]) {
e.preventDefault();
$('#' + map[cls]).val($(this).data('id'));
break;
}
}
});
});
</script>
@endpush