diff --git a/Modules/CostCalculator/app/Http/Controllers/.gitkeep b/Modules/CostCalculator/app/Http/Controllers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/app/Http/Controllers/CostCalculatorController.php b/Modules/CostCalculator/app/Http/Controllers/CostCalculatorController.php new file mode 100644 index 0000000..9fdd8b5 --- /dev/null +++ b/Modules/CostCalculator/app/Http/Controllers/CostCalculatorController.php @@ -0,0 +1,246 @@ +costCalculatorService = $costCalculatorService; + } + /** + * Display a listing of the resource. + */ + public function index(Request $request) + { + $data['title'] = 'Cost Calculator List'; + $data['costs'] = $this->costCalculatorService->findAll($request); + $data['countryOptions'] = Country::where('status', 1)->pluck('title', 'id'); + $data['programLevelOptions'] = ProgramLevel::where('status', 1)->pluck('title', 'id'); + $data['programOptions'] = Program::where('status', 1)->pluck('title', 'id'); + $data['livingStatusOptions'] = config('constants.living_status'); + + return view('costCalculator::cost.index', $data); + } + + /** + * Show the form for creating a new resource. + */ + public function create() + { + $data['title'] = 'Program Create'; + $data['editable'] = false; + $data['intakeOptions'] = Program::INTAKE; + $data['institutionOptions'] = Institution::where('status', 1)->pluck('title', 'id'); + $data['programLevelOptions'] = ProgramLevel::where('status', 1)->pluck('title', 'id'); + $data['testOptions'] = Test::where('status', 1)->where('parent_id', null)->pluck('title', 'id'); + + return view('coursefinder::program.create', $data); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request) + { + + $request->validate([ + 'title' => 'required', + ]); + + $input = $request->except(['prof_test_accepted']); + + DB::transaction(function () use ($input, $request) { + + $program = Program::create($input); + + $attachData = []; + + foreach ($request->prof_test_accepted as $item) { + $attachData[$item['test_id']] = [ + 'min_score' => $item['min_score'], + 'band_score' => $item['band_score'], + ]; + } + + $program->tests()->sync($attachData); + + flash()->success('Program has been created!'); + }); + + return redirect()->route('program.index'); + } + + /** + * Show the specified resource. + */ + public function show($id) + { + $data['title'] = 'View Program'; + $data['program'] = Program::findOrFail($id); + $data['intakeOptions'] = Program::INTAKE; + return view('coursefinder::program.show', $data); + } + + /** + * Show the form for editing the specified resource. + */ + public function edit($id) + { + $data['title'] = 'Edit Program'; + $data['editable'] = true; + $data['program'] = Program::findOrFail($id); + $data['intakeOptions'] = Program::INTAKE; + $data['institutionOptions'] = Institution::where('status', 1)->pluck('title', 'id'); + $data['programLevelOptions'] = ProgramLevel::where('status', 1)->pluck('title', 'id'); + $data['testOptions'] = Test::where('status', 1)->where('parent_id', null)->pluck('title', 'id'); + $data['coopOptions'] = Coop::where('status', 1)->pluck('title', 'id'); + $data['requiredDocumentOptions'] = RequiredDocument::where('status', 1)->pluck('title', 'id'); + return view('coursefinder::program.edit', $data); + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, $id) + { + $input = $request->except(['prof_test_accepted']); + + DB::transaction(function () use ($input, $request, $id) { + $program = Program::findOrFail($id); + $program->update($input); + + $attachData = []; + + foreach ($request->prof_test_accepted as $item) { + $attachData[$item['test_id']] = [ + 'min_score' => $item['min_score'], + 'band_score' => $item['band_score'], + ]; + } + + $program->tests()->sync($attachData); + }); + + flash()->success('program has been updated!'); + + return redirect()->route('program.index')->withSuccess('Program has been updated!'); + } + + /** + * Remove the specified resource from storage. + */ + public function destroy($id) + { + try { + $program = Program::findOrFail($id); + $program->delete(); + + flash()->success('Program has been deleted!'); + } catch (\Throwable $th) { + flash()->error($th->getMessage()); + } + return response()->json(['status' => 200, 'message' => 'Program has been deleted!'], 200); + } + + public function getProgramByInstitution(Request $request) + { + try { + $program = Program::where(['institution_id' => $request->institution_id]) + ->select('id', 'title') + ->get(); + return response()->json([ + 'status' => true, + 'data' => $program, + 'msg' => 'Fetch', + ], 200); + } catch (\Throwable $th) { + return response()->json([ + 'status' => false, + 'msg' => $th->getMessage(), + ], 500); + } + } + + public function import(Request $request) + { + DB::beginTransaction(); + try { + Excel::import(new ProgramImport(), $request->file('file')->store('temp')); + DB::commit(); + return redirect()->back()->with('success', "Upload Succesfully"); + } catch (\Throwable $th) { + DB::rollback(); + return redirect()->back()->with('error', $th->getMessage()); + } + } + + public function getCoursesList(Request $request) + { + $data['intakes'] = Program::INTAKE; + + $query = Program::query(); + + if ($request->filled('countries_id')) { + $query->whereRelation('institution', 'countries_id', $request->countries_id); + } + + if ($request->filled('institution_id')) { + $query->where('institutions_id', $request->institution_id); + } + + if ($request->filled('search')) { + $query->where('title', 'like', "%{$request->search}%"); + } + + if ($request->filled('programlevels_id')) { + $query->where('programlevels_id', $request->programlevels_id); + } + + if ($request->filled('intake_id')) { + $query->whereJsonContains('intakes', $request->intake_id); + } + + if ($request->filled('preffered_location')) { + $query->where('location', 'like', "%{$request->preffered_location}%"); + } + + if ($request->filled('service_id')) { + $query->whereRelation('services', 'service_id', '=', $request->service_id); + + if ($request->filled('min_score')) { + $query->whereRelation('services', 'min_score', '<=', $request->min_score); + } + + if ($request->filled('max_score')) { + $query->whereRelation('services', 'band_score', '<=', $request->max_score); + } + } + + $data['courses'] = $query + ->orderBy('title', 'asc') + ->paginate(10) + ->withQueryString(); + + $queryCount = $data['courses']->total(); + + if ($request->ajax()) { + $view = view('client.raffles.pages.course.list', $data)->render(); + return response()->json(['html' => $view, 'queryCount' => $queryCount]); + } + } +} diff --git a/Modules/CostCalculator/app/Models/CostCalculator.php b/Modules/CostCalculator/app/Models/CostCalculator.php new file mode 100644 index 0000000..3465741 --- /dev/null +++ b/Modules/CostCalculator/app/Models/CostCalculator.php @@ -0,0 +1,44 @@ + 'object', + 'accomodation_cost' => 'object', + 'onetime_cost' => 'object', + 'other_services' => 'object', + ]; + + public function institution() + { + return $this->belongsTo(Country::class, 'country_id'); + } + + public function programLevel() + { + return $this->belongsTo(ProgramLevel::class, 'programlevel_id'); + } + + public function program() + { + return $this->belongsTo(Program::class, 'program_id'); + } +} diff --git a/Modules/CostCalculator/app/Models/Scopes/.gitkeep b/Modules/CostCalculator/app/Models/Scopes/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/app/Providers/.gitkeep b/Modules/CostCalculator/app/Providers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/app/Providers/CostCalculatorServiceProvider.php b/Modules/CostCalculator/app/Providers/CostCalculatorServiceProvider.php new file mode 100644 index 0000000..8847a29 --- /dev/null +++ b/Modules/CostCalculator/app/Providers/CostCalculatorServiceProvider.php @@ -0,0 +1,135 @@ +registerCommands(); + $this->registerCommandSchedules(); + $this->registerTranslations(); + $this->registerConfig(); + $this->registerViews(); + $this->loadMigrationsFrom(module_path($this->name, 'database/migrations')); + } + + /** + * Register the service provider. + */ + public function register(): void + { + $this->app->register(EventServiceProvider::class); + $this->app->register(RouteServiceProvider::class); + } + + /** + * Register commands in the format of Command::class + */ + protected function registerCommands(): void + { + // $this->commands([]); + } + + /** + * Register command Schedules. + */ + protected function registerCommandSchedules(): void + { + // $this->app->booted(function () { + // $schedule = $this->app->make(Schedule::class); + // $schedule->command('inspire')->hourly(); + // }); + } + + /** + * Register translations. + */ + public function registerTranslations(): void + { + $langPath = resource_path('lang/modules/'.$this->nameLower); + + if (is_dir($langPath)) { + $this->loadTranslationsFrom($langPath, $this->nameLower); + $this->loadJsonTranslationsFrom($langPath); + } else { + $this->loadTranslationsFrom(module_path($this->name, 'lang'), $this->nameLower); + $this->loadJsonTranslationsFrom(module_path($this->name, 'lang')); + } + } + + /** + * Register config. + */ + protected function registerConfig(): void + { + $relativeConfigPath = config('modules.paths.generator.config.path'); + $configPath = module_path($this->name, $relativeConfigPath); + + if (is_dir($configPath)) { + $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($configPath)); + + foreach ($iterator as $file) { + if ($file->isFile() && $file->getExtension() === 'php') { + $relativePath = str_replace($configPath . DIRECTORY_SEPARATOR, '', $file->getPathname()); + $configKey = $this->nameLower . '.' . str_replace([DIRECTORY_SEPARATOR, '.php'], ['.', ''], $relativePath); + $key = ($relativePath === 'config.php') ? $this->nameLower : $configKey; + + $this->publishes([$file->getPathname() => config_path($relativePath)], 'config'); + $this->mergeConfigFrom($file->getPathname(), $key); + } + } + } + } + + /** + * Register views. + */ + public function registerViews(): void + { + $viewPath = resource_path('views/modules/'.$this->nameLower); + $sourcePath = module_path($this->name, 'resources/views'); + + $this->publishes([$sourcePath => $viewPath], ['views', $this->nameLower.'-module-views']); + + $this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->nameLower); + + $componentNamespace = $this->module_namespace($this->name, $this->app_path(config('modules.paths.generator.component-class.path'))); + Blade::componentNamespace($componentNamespace, $this->nameLower); + } + + /** + * Get the services provided by the provider. + */ + public function provides(): array + { + return []; + } + + private function getPublishableViewPaths(): array + { + $paths = []; + foreach (config('view.paths') as $path) { + if (is_dir($path.'/modules/'.$this->nameLower)) { + $paths[] = $path.'/modules/'.$this->nameLower; + } + } + + return $paths; + } +} diff --git a/Modules/CostCalculator/app/Providers/EventServiceProvider.php b/Modules/CostCalculator/app/Providers/EventServiceProvider.php new file mode 100644 index 0000000..cbd8e97 --- /dev/null +++ b/Modules/CostCalculator/app/Providers/EventServiceProvider.php @@ -0,0 +1,30 @@ +> + */ + protected $listen = []; + + /** + * Indicates if events should be discovered. + * + * @var bool + */ + protected static $shouldDiscoverEvents = true; + + /** + * Configure the proper event listeners for email verification. + */ + protected function configureEmailVerification(): void + { + // + } +} diff --git a/Modules/CostCalculator/app/Providers/RouteServiceProvider.php b/Modules/CostCalculator/app/Providers/RouteServiceProvider.php new file mode 100644 index 0000000..dfafb7f --- /dev/null +++ b/Modules/CostCalculator/app/Providers/RouteServiceProvider.php @@ -0,0 +1,50 @@ +mapApiRoutes(); + $this->mapWebRoutes(); + } + + /** + * Define the "web" routes for the application. + * + * These routes all receive session state, CSRF protection, etc. + */ + protected function mapWebRoutes(): void + { + Route::middleware('web')->group(module_path($this->name, '/routes/web.php')); + } + + /** + * Define the "api" routes for the application. + * + * These routes are typically stateless. + */ + protected function mapApiRoutes(): void + { + Route::middleware('api')->prefix('api')->name('api.')->group(module_path($this->name, '/routes/api.php')); + } +} diff --git a/Modules/CostCalculator/app/Services/.gitkeep b/Modules/CostCalculator/app/Services/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/app/Services/CostCalculatorService.php b/Modules/CostCalculator/app/Services/CostCalculatorService.php new file mode 100644 index 0000000..39e30c2 --- /dev/null +++ b/Modules/CostCalculator/app/Services/CostCalculatorService.php @@ -0,0 +1,53 @@ +filled('country_id')) { + $query->whereRelation('institution', 'country_id', $request->country_id); + } + + if ($request->filled('institution_id')) { + $query->where("institution_id", $request->institution_id); + } + + if ($request->filled('programlevel_id')) { + $query->where("programlevel_id", $request->programlevel_id); + } + + if ($request->filled('intake_id')) { + $intakeId = $request->intake_id; + $query->whereJsonContains('intakes', $intakeId); + } + + if ($request->filled('status')) { + $query->where('status', $request->status); + } + + if ($request->filled('search')) { + $search = $request->search; + $query->where('title', 'like', "%{$search}%"); + } + + if ($request->filled('location')) { + $location = $request->location; + $query->where('location', 'like', "%{$location}%"); + } + })->latest()->paginate(10)->withQueryString(); + } + + public function pluck(callable $query = null) + { + $baseQuery = CostCalculator::query(); + if (is_callable($query)) { + $query($baseQuery); + } + return $baseQuery->pluck('title', 'id'); + } +} diff --git a/Modules/CostCalculator/composer.json b/Modules/CostCalculator/composer.json new file mode 100644 index 0000000..b1ae184 --- /dev/null +++ b/Modules/CostCalculator/composer.json @@ -0,0 +1,30 @@ +{ + "name": "nwidart/costcalculator", + "description": "", + "authors": [ + { + "name": "Nicolas Widart", + "email": "n.widart@gmail.com" + } + ], + "extra": { + "laravel": { + "providers": [], + "aliases": { + + } + } + }, + "autoload": { + "psr-4": { + "Modules\\CostCalculator\\": "app/", + "Modules\\CostCalculator\\Database\\Factories\\": "database/factories/", + "Modules\\CostCalculator\\Database\\Seeders\\": "database/seeders/" + } + }, + "autoload-dev": { + "psr-4": { + "Modules\\CostCalculator\\Tests\\": "tests/" + } + } +} diff --git a/Modules/CostCalculator/config/.gitkeep b/Modules/CostCalculator/config/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/config/config.php b/Modules/CostCalculator/config/config.php new file mode 100644 index 0000000..dab8c60 --- /dev/null +++ b/Modules/CostCalculator/config/config.php @@ -0,0 +1,5 @@ + 'CostCalculator', +]; diff --git a/Modules/CostCalculator/database/factories/.gitkeep b/Modules/CostCalculator/database/factories/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/database/migrations/.gitkeep b/Modules/CostCalculator/database/migrations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/database/migrations/2025_08_13_102211_create_cost_calculators_table.php b/Modules/CostCalculator/database/migrations/2025_08_13_102211_create_cost_calculators_table.php new file mode 100644 index 0000000..046d2a4 --- /dev/null +++ b/Modules/CostCalculator/database/migrations/2025_08_13_102211_create_cost_calculators_table.php @@ -0,0 +1,38 @@ +id(); + $table->unsignedInteger('country_id')->nullable(); + $table->unsignedInteger('programlevel_id')->nullable(); + $table->unsignedInteger('program_id')->nullable(); + $table->unsignedInteger('living_status_id')->nullable(); + $table->json('living_cost')->nullable(); + $table->json('accomodation_cost')->nullable(); + $table->json('onetime_cost')->nullable(); + $table->json('other_services')->nullable(); + $table->unsignedInteger('createdby')->nullable(); + $table->unsignedInteger('updatedby')->nullable(); + $table->boolean('status')->default(1); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('cost_calculators'); + } +}; diff --git a/Modules/CostCalculator/database/seeders/.gitkeep b/Modules/CostCalculator/database/seeders/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/database/seeders/CostCalculatorDatabaseSeeder.php b/Modules/CostCalculator/database/seeders/CostCalculatorDatabaseSeeder.php new file mode 100644 index 0000000..dffd91c --- /dev/null +++ b/Modules/CostCalculator/database/seeders/CostCalculatorDatabaseSeeder.php @@ -0,0 +1,16 @@ +call([]); + } +} diff --git a/Modules/CostCalculator/module.json b/Modules/CostCalculator/module.json new file mode 100644 index 0000000..72a6482 --- /dev/null +++ b/Modules/CostCalculator/module.json @@ -0,0 +1,11 @@ +{ + "name": "CostCalculator", + "alias": "costcalculator", + "description": "", + "keywords": [], + "priority": 0, + "providers": [ + "Modules\\CostCalculator\\Providers\\CostCalculatorServiceProvider" + ], + "files": [] +} diff --git a/Modules/CostCalculator/package.json b/Modules/CostCalculator/package.json new file mode 100644 index 0000000..d6fbfc8 --- /dev/null +++ b/Modules/CostCalculator/package.json @@ -0,0 +1,15 @@ +{ + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build" + }, + "devDependencies": { + "axios": "^1.1.2", + "laravel-vite-plugin": "^0.7.5", + "sass": "^1.69.5", + "postcss": "^8.3.7", + "vite": "^4.0.0" + } +} diff --git a/Modules/CostCalculator/resources/assets/js/app.js b/Modules/CostCalculator/resources/assets/js/app.js new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/resources/assets/sass/app.scss b/Modules/CostCalculator/resources/assets/sass/app.scss new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/resources/views/.gitkeep b/Modules/CostCalculator/resources/views/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/resources/views/cost/create.blade.php b/Modules/CostCalculator/resources/views/cost/create.blade.php new file mode 100644 index 0000000..50dbc42 --- /dev/null +++ b/Modules/CostCalculator/resources/views/cost/create.blade.php @@ -0,0 +1,10 @@ +@extends('layouts.app') +@section('content') +
+ + + {{ html()->form('POST')->route('costCalculator.store')->class(['needs-validation'])->attributes(['novalidate', 'enctype' => 'multipart/form-data', 'onkeydown' => "return event.key != 'Enter';"])->open() }} + @include('costCalculator::cost.partials.form') + {{ html()->form()->close() }} +
+@endsection diff --git a/Modules/CostCalculator/resources/views/cost/edit.blade.php b/Modules/CostCalculator/resources/views/cost/edit.blade.php new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/resources/views/cost/index.blade.php b/Modules/CostCalculator/resources/views/cost/index.blade.php new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/resources/views/cost/partials/form.blade.php b/Modules/CostCalculator/resources/views/cost/partials/form.blade.php new file mode 100644 index 0000000..0f7e25d --- /dev/null +++ b/Modules/CostCalculator/resources/views/cost/partials/form.blade.php @@ -0,0 +1,326 @@ +
+
+
+
+
+
+
Cost Calculator
+
+
+ +
+
+
+
+
+
+ {{ html()->label('Country')->class('form-label') }} + {{ html()->span('*')->class('text-danger') }} + {{ html()->select('country_id', $countryOptions)->placeholder('Select')->class('form-select choices-select')->required() }} + {{ html()->div('Please select country')->class('invalid-feedback') }} +
+ +
+ {{ html()->label('Program Level')->class('form-label')->for('programlevel_id') }} + {{ html()->span('*')->class('text-danger') }} + {{ html()->select('programlevel_id', $programLevelOptions)->placeholder('Select')->class('form-select choices-select')->required() }} + {{ html()->div('Please select program level')->class('invalid-feedback') }} +
+ +
+ {{ html()->label('Living Status')->class('form-label')->for('institution_id') }} + {{ html()->span('*')->class('text-danger') }} + {{ html()->select('living_status_id', $livingStatusOptions)->placeholder('Select')->class('form-select choices-select')->required() }} + {{ html()->div('Please select Living Status')->class('invalid-feedback') }} +
+ +
+ {{ html()->label('Program')->class('form-label')->for('program_id') }} + {{ html()->span('*')->class('text-danger') }} + {{ html()->select('program_id', $programOptions)->placeholder('Select')->class('form-select choices-select')->required() }} + {{ html()->div('Please select program')->class('invalid-feedback') }} +
+
+
+
+
+
+ +
+
+ +
+
+
+
+
Living Cost
+
+
+ +
+
+
+
+
+ + + + + + + + + + @if ($editable) + @if ($program->level) + + @forelse ($program->level as $key => $item) + @include('coursefinder::program.partials.qualification-form', [ + 'numInc' => $key, + 'value' => $item, + ]) + @empty + @endforelse + @else + @include('coursefinder::program.partials.qualification-form', [ + 'numInc' => 0, + ]) + + @endif + @else + @include('coursefinder::program.partials.qualification-form', [ + 'numInc' => 0, + ]) + @endif + +
MonthlyYearly
+
+
+
+ +
+
+
+
+
Accomodation Cost
+
+
+ +
+
+
+
+
+ + + + + + + + + + @if ($editable) + @forelse ($program->tests as $key => $item) + @include('coursefinder::program.partials.proficiency-form', [ + 'numInc' => $key, + 'value' => $item, + ]) + @empty + @include('coursefinder::program.partials.proficiency-form', [ + 'numInc' => 0, + ]) + @endforelse + @else + @include('coursefinder::program.partials.proficiency-form', [ + 'numInc' => 0, + ]) + @endif + +
MonthlyYearly
+
+
+ +
+ + +
+
+
+
+
One Time Cost (Non-Refundable)
+
+
+ +
+
+
+
+
+ + + + + + + + + + + + @if ($editable) + @if ($program->fee_breakdown) + @forelse ($program->fee_breakdown as $key => $item) + @include('coursefinder::program.partials.feeBreakdown', [ + 'numInc' => $key, + 'value' => $item, + ]) + @empty + @endforelse + @else + @include('coursefinder::program.partials.feeBreakdown', [ + 'numInc' => 0, + ]) + + @endif + @else + @include('coursefinder::program.partials.feeBreakdown', [ + 'numInc' => 0, + ]) + @endif + +
VisaBiometricsSevisApplication
+
+
+
+ +
+
+
+
+
Other Services
+
+
+ +
+
+
+
+
+ + + + + + + + + + + @if ($editable) + @if ($program->course_module) + @forelse ($program->course_module as $key => $item) + @include('coursefinder::program.partials.courseModule', [ + 'numInc' => $key, + 'value' => $item, + ]) + @empty + @endforelse + @else + @include('coursefinder::program.partials.courseModule', [ + 'numInc' => 0, + ]) + + @endif + @else + @include('coursefinder::program.partials.courseModule', [ + 'numInc' => 0, + ]) + @endif + +
Flight TicketHealth InsuranceExtra
+
+
+
+ +
+ Cancel + + +
+
+ +
+ +@push('js') + +@endpush diff --git a/Modules/CostCalculator/resources/views/cost/show.blade.php b/Modules/CostCalculator/resources/views/cost/show.blade.php new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/resources/views/index.blade.php b/Modules/CostCalculator/resources/views/index.blade.php new file mode 100644 index 0000000..e1eaa06 --- /dev/null +++ b/Modules/CostCalculator/resources/views/index.blade.php @@ -0,0 +1,7 @@ +@extends('costcalculator::layouts.master') + +@section('content') +

Hello World

+ +

Module: {!! config('costcalculator.name') !!}

+@endsection diff --git a/Modules/CostCalculator/resources/views/layouts/master.blade.php b/Modules/CostCalculator/resources/views/layouts/master.blade.php new file mode 100644 index 0000000..7d137fd --- /dev/null +++ b/Modules/CostCalculator/resources/views/layouts/master.blade.php @@ -0,0 +1,29 @@ + + + + + + + + + + CostCalculator Module - {{ config('app.name', 'Laravel') }} + + + + + + + + + + {{-- Vite CSS --}} + {{-- {{ module_vite('build-costcalculator', 'resources/assets/sass/app.scss', storage_path('vite.hot')) }} --}} + + + + @yield('content') + + {{-- Vite JS --}} + {{-- {{ module_vite('build-costcalculator', 'resources/assets/js/app.js', storage_path('vite.hot')) }} --}} + diff --git a/Modules/CostCalculator/routes/.gitkeep b/Modules/CostCalculator/routes/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Modules/CostCalculator/routes/api.php b/Modules/CostCalculator/routes/api.php new file mode 100644 index 0000000..0262fce --- /dev/null +++ b/Modules/CostCalculator/routes/api.php @@ -0,0 +1,19 @@ +prefix('v1')->group(function () { + Route::apiResource('costcalculator', CostCalculatorController::class)->names('costcalculator'); +}); diff --git a/Modules/CostCalculator/routes/web.php b/Modules/CostCalculator/routes/web.php new file mode 100644 index 0000000..b403665 --- /dev/null +++ b/Modules/CostCalculator/routes/web.php @@ -0,0 +1,19 @@ +names('costcalculator'); +}); diff --git a/Modules/CostCalculator/vite.config.js b/Modules/CostCalculator/vite.config.js new file mode 100644 index 0000000..34a4241 --- /dev/null +++ b/Modules/CostCalculator/vite.config.js @@ -0,0 +1,57 @@ +import { defineConfig } from 'vite'; +import laravel from 'laravel-vite-plugin'; +import { readdirSync, statSync } from 'fs'; +import { join,relative,dirname } from 'path'; +import { fileURLToPath } from 'url'; + +export default defineConfig({ + build: { + outDir: '../../public/build-costcalculator', + emptyOutDir: true, + manifest: true, + }, + plugins: [ + laravel({ + publicDirectory: '../../public', + buildDirectory: 'build-costcalculator', + input: [ + __dirname + '/resources/assets/sass/app.scss', + __dirname + '/resources/assets/js/app.js' + ], + refresh: true, + }), + ], +}); +// Scen all resources for assets file. Return array +//function getFilePaths(dir) { +// const filePaths = []; +// +// function walkDirectory(currentPath) { +// const files = readdirSync(currentPath); +// for (const file of files) { +// const filePath = join(currentPath, file); +// const stats = statSync(filePath); +// if (stats.isFile() && !file.startsWith('.')) { +// const relativePath = 'Modules/CostCalculator/'+relative(__dirname, filePath); +// filePaths.push(relativePath); +// } else if (stats.isDirectory()) { +// walkDirectory(filePath); +// } +// } +// } +// +// walkDirectory(dir); +// return filePaths; +//} + +//const __filename = fileURLToPath(import.meta.url); +//const __dirname = dirname(__filename); + +//const assetsDir = join(__dirname, 'resources/assets'); +//export const paths = getFilePaths(assetsDir); + + +//export const paths = [ +// 'Modules/CostCalculator/resources/assets/sass/app.scss', +// 'Modules/CostCalculator/resources/assets/js/app.js', +//]; diff --git a/config/constants.php b/config/constants.php index 481f437..ad4bfc9 100644 --- a/config/constants.php +++ b/config/constants.php @@ -78,4 +78,9 @@ return [ 14 => 'Archived', ], + 'living_status'=> [ + 1 => 'Alone', + 2 => 'With Spouse', + 3 => 'With Spouse and Child', + ] ]; diff --git a/modules_statuses.json b/modules_statuses.json index 87133bc..1a2ed1d 100644 --- a/modules_statuses.json +++ b/modules_statuses.json @@ -17,5 +17,6 @@ "Admin": true, "Drive": true, "Sitemap": true, - "Document": true + "Document": true, + "CostCalculator": true } \ No newline at end of file diff --git a/public/raffles/assets/js/style.js b/public/raffles/assets/js/style.js index 74a9426..ac5951a 100644 --- a/public/raffles/assets/js/style.js +++ b/public/raffles/assets/js/style.js @@ -584,16 +584,17 @@ document.addEventListener('keydown', e => { }); +// cost calculator progress // cost calculator progress let currentStep = 1; -const totalSteps = 5; +const totalSteps = 7; // updated to match HTML const monkey = document.getElementById('monkey').querySelector('img'); const monkeyContainer = document.getElementById('monkey'); -const nextBtn = document.querySelector('.next-btn button'); +const nextBtn = document.getElementById('nextBtn'); +const doneBtn = document.getElementById('doneBtn'); const bananalast = document.getElementById('b5'); - const monkeyImages = [ "/raffles/assets/images/icons/monkey1.png", "/raffles/assets/images/icons/monkey2.png", @@ -608,33 +609,25 @@ nextBtn.addEventListener('click', () => { if (currentStep < totalSteps) { currentStep++; - // Move monkey + // Calculate monkey position based on window width + let percent; if (window.innerWidth <= 540) { - const percent = ((currentStep - 1) / (totalSteps - 0.2)) * 100; - monkeyContainer.style.left = percent + '%'; - } - else if (window.innerWidth <= 768) { - const percent = ((currentStep - 1) / (totalSteps - 0.3)) * 100; - monkeyContainer.style.left = percent + '%'; - } - else if (window.innerWidth <= 992) { - const percent = ((currentStep - 1) / (totalSteps - 0.7)) * 100; - monkeyContainer.style.left = percent + '%'; - } - else if (window.innerWidth <= 1180) { - const percent = ((currentStep - 1) / (totalSteps - 0.2)) * 100; - monkeyContainer.style.left = percent + '%'; - } - else { - const percent = ((currentStep - 1) / (totalSteps - 0.5)) * 100; - monkeyContainer.style.left = percent + '%'; + percent = ((currentStep - 1) / (totalSteps - 0.2)) * 100; + } else if (window.innerWidth <= 768) { + percent = ((currentStep - 1) / (totalSteps - 0.3)) * 100; + } else if (window.innerWidth <= 992) { + percent = ((currentStep - 1) / (totalSteps - 0.7)) * 100; + } else if (window.innerWidth <= 1180) { + percent = ((currentStep - 1) / (totalSteps - 0.2)) * 100; + } else { + percent = ((currentStep - 1) / (totalSteps - 0.5)) * 100; } + monkeyContainer.style.left = percent + '%'; - - // Change monkey image + // Update monkey image monkey.src = monkeyImages[currentStep - 1]; - // Update step content + // Switch step content const currentContent = document.getElementById('step' + (currentStep - 1)); const nextContent = document.getElementById('step' + currentStep); if (currentContent && nextContent) { @@ -642,30 +635,29 @@ nextBtn.addEventListener('click', () => { nextContent.classList.add('active'); } - // At final step (Step 5), hide Next and show Done + // Show done button on last step if (currentStep === totalSteps) { nextBtn.style.display = 'none'; doneBtn.style.display = 'block'; } - } w + } }); + doneBtn.addEventListener('click', () => { bananalast.classList.add('active'); if (window.innerWidth <= 992) { - // On mobile: show 7th image and move down - monkey.src = monkeyImages[6]; // 7th image (index 6) + monkey.src = monkeyImages[6]; // last image monkeyContainer.style.top = '142%'; - monkeyContainer.style.left = '40%'; // Optional: keep it centered or adjust as needed + monkeyContainer.style.left = '40%'; } else { - // On desktop: show 6th image and move right - monkey.src = monkeyImages[5]; // 6th image (index 5) + monkey.src = monkeyImages[5]; monkeyContainer.style.left = '110%'; - monkeyContainer.style.top = '-120%'; // Reset top if changed previously + monkeyContainer.style.top = '-120%'; } }); -// Final monkey image + diff --git a/resources/views/client/raffles/pages/cost-calculator.blade.php b/resources/views/client/raffles/pages/cost-calculator.blade.php index 495b753..a2af845 100644 --- a/resources/views/client/raffles/pages/cost-calculator.blade.php +++ b/resources/views/client/raffles/pages/cost-calculator.blade.php @@ -19,158 +19,263 @@
-
+ {{-- @csrf - + --}} -
+
-
-

Choose items to find the total cost

-
Where do you want to study?
+
+

Choose items to find the total cost

+
Which country are you planning to study + in?
-
- @foreach ($countryOptions as $id => $country) - - @endforeach -
-
- -
-

Choose items to find the total cost

-
Which English Proficiency Do you Have? -
- -
- @foreach ($testOptions as $id => $test) - - @endforeach -
-
- -
-

Choose items to find the total cost

-
Which Intake do you want to go?
- -
- @foreach ($intakeOptions as $id => $intake) - - @endforeach -
-
- -
-

Choose items to find the total cost

-
How long do you want to study
- -
+
+ @foreach ($countryOptions as $id => $country) + @endforeach +
+
+ +
+

Choose items to find the total cost

+
Which level are you applying for?
+ +
+ @foreach ($programLevelOptions as $id => $level)
-
- -
+ @endforeach
+
-
-

Choose items to find the total cost

-
Whats Your Program Level Choice?
+
+

Choose items to find the total cost

+
Are you going alone or with a dependent? +
-
- @foreach ($programLevelOptions as $id => $level) - - @endforeach +
+
+
-
- -
- - -
- -
-
- -
-
- -
-
- -
-
- -
-
- + -
- + +
+

Choose items to find the total cost

+
Cost of Living
+ + +
+ +
+

Choose items to find the total cost

+
Accomodation cost per year:
+ + +
+ +
+

Choose items to find the total cost

+
Non-Refundable onetime cost in + processing:
+ + +
+ +
+

Choose items to find the total cost

+
Do you want to include other services? +
+ +
+ + +
+ +
+
+
+ +
+ + +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+ {{-- --}}
@@ -225,7 +330,7 @@ @endsection -@push('js') +{{-- @push('js') -@endpush +@endpush --}}