Skip to content

Commit

Permalink
Scenery > Flights
Browse files Browse the repository at this point in the history
Add flight search capability to My Sceneries page
  • Loading branch information
FatihKoz committed Apr 9, 2024
1 parent ac93672 commit 2d4aabd
Show file tree
Hide file tree
Showing 6 changed files with 349 additions and 5 deletions.
76 changes: 76 additions & 0 deletions Http/Controllers/DB_SceneryController.php
Expand Up @@ -3,9 +3,12 @@
namespace Modules\DisposableBasic\Http\Controllers;

use App\Contracts\Controller;
use App\Models\Bid;
use App\Models\Flight;
use App\Services\UserService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Modules\DisposableBasic\Models\DB_Scenery;
use Modules\DisposableBasic\Models\Enums\DB_Simulator;
Expand Down Expand Up @@ -54,6 +57,79 @@ public function index(Request $request)
]);
}

public function flights(Request $request)
{
$type = $request->input('type');

if (!in_array($type, ['arrivals', 'departures', 'trips'])) {
$type = 'arrivals';
}

$search_arrs = $type === 'arrivals' ? true : false;
$search_deps = $type === 'departures' ? true : false;
$search_trips = $type === 'trips' ? true : false;

$user = Auth::user();
$user_sceneries = DB_Scenery::where('user_id', $user->id)->groupBy('airport_id')->pluck('airport_id')->toArray();

$where = [
'active' => true,
'visible' => true,
];

if (setting('pilots.restrict_to_company')) {
$where['airline_id'] = $user->airline_id;
}

if (setting('pilots.only_flights_from_current')) {
$where['dpt_airport_id'] = $user->curr_airport_id;
}

$filter_by_user = (setting('pireps.restrict_aircraft_to_rank', true) || setting('pireps.restrict_aircraft_to_typerating', false)) ? true : false;

if ($filter_by_user) {
$user_service = app(UserService::class);
$user_subfleets = $user_service->getAllowableSubfleets($user)->pluck('id')->toArray();
$user_flights = DB::table('flight_subfleet')->select('flight_id')->whereIn('subfleet_id', $user_subfleets)->groupBy('flight_id')->pluck('flight_id')->toArray();
$open_flights = Flight::withCount('subfleets')->whereNull('user_id')->having('subfleets_count', 0)->pluck('id')->toArray();
$allowed_flights = array_merge($user_flights, $open_flights);
} else {
$allowed_flights = [];
}

$myflights = Flight::with(['airline', 'dpt_airport', 'arr_airport', 'simbrief'])->where($where)->whereNull('user_id')->when($search_deps, function ($query) use ($user_sceneries) {
return $query->whereIn('dpt_airport_id', $user_sceneries);
})->when($search_arrs, function ($query) use ($user_sceneries) {
return $query->whereIn('arr_airport_id', $user_sceneries);
})->when($search_trips, function ($query) use ($user_sceneries) {
return $query->whereIn('dpt_airport_id', $user_sceneries)->whereIn('arr_airport_id', $user_sceneries);
})->when($filter_by_user, function ($query) use ($allowed_flights) {
return $query->whereIn('id', $allowed_flights);
})->sortable(['flight_number', 'route_code', 'route_leg'])->paginate(25);

$saved_flights = [];
$bids = Bid::where('user_id', $user->id)->get();
foreach ($bids as $bid) {
if (!$bid->flight) {
$bid->delete();
continue;
}

$saved_flights[$bid->flight_id] = $bid->id;
}

return view('DBasic::scenery.flights', [
'flights' => $myflights,
'units' => DB_GetUnits(),
'type' => $type,
'user' => $user,
'saved' => $saved_flights,
'simbrief' => !empty(setting('simbrief.api_key')),
'simbrief_bids' => setting('simbrief.only_bids'),
'acars_plugin' => check_module('VMSAcars'),
]);
}

public function store(Request $request)
{
if (!$request->airport_id || strlen($request->airport_id) != 4) {
Expand Down
1 change: 1 addition & 0 deletions Providers/DB_ServiceProvider.php
Expand Up @@ -72,6 +72,7 @@ protected function registerRoutes()
Route::get('dpireps', 'DB_PirepController@index')->name('pireps');
// Scenery List
Route::get('dscenery', 'DB_SceneryController@index')->name('scenery');
Route::get('dflights', 'DB_SceneryController@flights')->name('scenery.flights');
Route::post('dscenery/store', 'DB_SceneryController@store')->name('scenery.store');
Route::post('dscenery/delete', 'DB_SceneryController@delete')->name('scenery.delete');
// Stable Approach
Expand Down
60 changes: 60 additions & 0 deletions Resources/views/scenery/flights.blade.php
@@ -0,0 +1,60 @@
@extends('app')
@section('title', 'My Sceneries')

@section('content')
<div class="row">
<div class="col-lg-10">
<div class="card mb-2">
<div class="card-header p-1">
<h5 class="m-1">
Flights For My Sceneries @if(filled($type)) | {{ ucfirst($type) }} @endif
<i class="fas fa-book-open float-end"></i>
</h5>
</div>
<div class="card-body table-responsive p-0">
@if($flights->count() > 0)
@include('DBasic::scenery.flights_table')
@else
<span class="m-1">No flights found compatible with your sceneries</span>
@endif
</div>
<div class="card-footer p-0 px-1 text-end small fw-bold">
@lang('DBasic::common.paginate', ['first' => $flights->firstItem(), 'last' => $flights->lastItem(), 'total' => $flights->total()])
</div>
</div>
{{ $flights->withQueryString()->links('pagination.default') }}
</div>
<div class="col-lg-2">
<div class="text-start d-grid mb-2">
<a href="{{ route('DBasic.scenery') }}" class="btn btn-sm btn-success px-1 py-0 mb-2">My Sceneries</a>
@if(!setting('pilots.only_flights_from_current'))
<a href="{{ route('DBasic.scenery.flights', ['type' => 'departures']) }}" class="btn btn-sm btn-warning px-1 py-0 mb-2">Search Departure Flights</a>
@endif
<a href="{{ route('DBasic.scenery.flights', ['type' => 'arrivals']) }}" class="btn btn-sm btn-warning px-1 py-0 mb-2">Search Arrival Flights</a>
<a href="{{ route('DBasic.scenery.flights', ['type' => 'trips']) }}" class="btn btn-sm btn-warning px-1 py-0 mb-2">Search Round Trip Flights</a>
</div>
</div>
</div>

@if(setting('bids.block_aircraft', false))
<div class="modal fade" id="bidModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="addBidLabel" aria-hidden="true">
<div class="modal-dialog mx-auto">
<div class="modal-content">
<div class="modal-header border-0 p-1">
<h5 class="modal-title m-0" id="bidModalLabel">Aircraft Selection</h5>
<button type="button" class="btn-close shadow-none" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<select name="bidaircraftdropdown" id="aircraft_select" class="bid_aircraft form-control"></select>
</div>
<div class="modal-footer border-0 p-1">
<button type="button" id="without_aircraft" class="btn btn-sm btn-danger m-0 mx-1 p-0 px-1" data-bs-dismiss="modal">Don't Book Aircraft</button>
<button type="button" id="with_aircraft" class="btn btn-sm btn-success m-0 mx-1 p-0 px-1" data-bs-dismiss="modal">Book Aircraft</button>
</div>
</div>
</div>
</div>
@endif
@endsection

@include('DBasic::scenery.flights_scripts')
112 changes: 112 additions & 0 deletions Resources/views/scenery/flights_scripts.blade.php
@@ -0,0 +1,112 @@
@section('scripts')
@parent
@if (setting('bids.block_aircraft', false))
<script>
$(document).ready(function() {
let aircrafts = [{ id: 0, text: 'Loading Aircrafts...'}];
let sel = $('#aircraft_select');
$("button.save_flight").click(function(e) {
e.preventDefault();
const btn = $(this);
const class_name = btn.attr('x-saved-class'); // classname to use is set on the element
const flight_id = btn.attr('x-id');
$('#aircraft_select').attr('x-saved-class', class_name)
$('#aircraft_select').attr('x-id', flight_id)
if (!btn.hasClass(class_name)) {
// $('#bidModal').modal();
let bidModal = new bootstrap.Modal(document.getElementById('bidModal'));
bidModal.show();
$.ajax(
{
headers: {'X-API-KEY': $('meta[name="api-key"]').attr('content')},
url: '{{ Config::get('app.url') }}/api/flights/' + flight_id + '/aircraft'
}).then((response) => {
aircrafts = [];
const results = response.map(ac => {
const text = `[${ac.icao}] ${ac.registration} ${ac.registration !== ac.name ? ` ${ac.name}` : ''}`;
aircrafts.push({ id: ac.id, text: text})
});
$('#aircraft_select option').remove();
if (aircrafts.length === 0) $('#with_aircraft').hide()
else $('#with_aircraft').show()
sel.select2({ dropdownParent: $('#bidModal'), data: aircrafts});
});
} else {
phpvms.bids.removeBid(flight_id).then(() => {
console.log('successfully removed flight');
btn.removeClass(class_name);
alert('@lang('flights.bidremoved')');
location.reload();
}).catch((error) => {
if (error.response && error.response.data) alert(`Error removing bid: ${error.response.data.details}`)
else alert(`Error removing bid: ${error.message}`)
});
}
});
$('#with_aircraft').click(() => {
const ac_id = $('#aircraft_select').val()
const flight_id = $('#aircraft_select').attr('x-id');
const class_name = $('#aircraft_select').attr('x-saved-class')
phpvms.bids.addBid(flight_id, ac_id).then(() => {
console.log('successfully saved flight');
$('button.save_flight[x-id="' + flight_id + '"]').addClass(class_name);
alert('@lang('flights.bidadded')');
location.replace('/flights/bids');
}).catch((error) => {
if (error.response && error.response.data) alert(`Error adding bid: ${error.response.data.details}`)
else alert(`Error adding bid: ${error.message}`)
});
});
$('#without_aircraft').click(async () => {
const flight_id = $('#aircraft_select').attr('x-id');
const class_name = $('#aircraft_select').attr('x-saved-class')
phpvms.bids.addBid(flight_id).then(() => {
console.log('successfully saved flight');
$('button.save_flight[x-id="' + flight_id + '"]').addClass(class_name);
alert('@lang('flights.bidadded')');
location.replace('/flights/bids');
}).catch((error) => {
if (error.response && error.response.data) alert(`Error adding bid: ${error.response.data.details}`)
else alert(`Error adding bid: ${error.message}`)
});
});
});
</script>
@else
<script>
$(document).ready(function() {
$("button.save_flight").click(function(e) {
e.preventDefault();
const btn = $(this);
const class_name = btn.attr('x-saved-class'); // classname to use is set on the element
const flight_id = btn.attr('x-id');
if (!btn.hasClass(class_name)) {
phpvms.bids.addBid(flight_id).then(() => {
console.log('successfully saved flight');
btn.addClass(class_name);
alert('@lang('flights.bidadded')');
location.replace('/flights/bids');
}).catch((error) => {
if (error.response && error.response.data) alert(`Error adding bid: ${error.response.data.details}`)
else alert(`Error adding bid: ${error.message}`)
});
} else {
phpvms.bids.removeBid(flight_id).then(() => {
console.log('successfully removed flight');
btn.removeClass(class_name);
alert('@lang('flights.bidremoved')');
location.reload();
}).catch((error) => {
if (error.response && error.response.data) alert(`Error removing bid: ${error.response.data.details}`)
else alert(`Error removing bid: ${error.message}`)
});
}
});
});
</script>
@endif
@endsection
88 changes: 88 additions & 0 deletions Resources/views/scenery/flights_table.blade.php
@@ -0,0 +1,88 @@
<table class="table table-sm table-borderless table-striped text-start text-nowrap align-middle mb-0">
<tr>
<th>@sortablelink('airline_id', 'Airline')</th>
<th>@sortablelink('flight_number', 'Flight No')</th>
<th>@sortablelink('route_code', 'Code')</th>
<th>@sortablelink('route_leg', 'Leg #')</th>
<th>@sortablelink('dpt_airport_id', 'Origin')</th>
<th class="text-center">STD</th>
<th class="text-center">STA</th>
<th>@sortablelink('arr_airport_id', 'Destination')</th>
<th class="text-center">@sortablelink('distance', 'Distance')</th>
<th class="text-center">@sortablelink('flight_time', 'Block Time')</th>
<th class="text-end">Actions</th>
</tr>
@foreach($flights as $flight)
<tr>
<td>
<a href="{{ route('DBasic.airline', [optional($flight->airline)->icao ?? '']) }}">
{{ optional($flight->airline)->name }}
</a>
</td>
<td>
<a href="{{ route('frontend.flights.show', [$flight->id]) }}">
{{ optional($flight->airline)->code.' '.$flight->flight_number }}
</a>
</td>
<td>{{ $flight->route_code }}</td>
<td>{{ $flight->route_leg }}</td>
<td>
<img class="img-mh25 me-1" title="{{ strtoupper(optional($flight->dpt_airport)->country) }}" src="{{ public_asset('/image/flags_new/'.strtolower(optional($flight->dpt_airport)->country).'.png') }}" alt=""/>
<a href="{{ route('frontend.airports.show', [$flight->dpt_airport_id]) }}">{{ optional($flight->dpt_airport)->full_name ?? $flight->dpt_airport_id }}</a>
</td>
<td class="text-center">{{ DB_FormatScheduleTime($flight->dpt_time) }}</td>
<td class="text-center">{{ DB_FormatScheduleTime($flight->arr_time) }}</td>
<td>
<img class="img-mh25 me-1" title="{{ strtoupper(optional($flight->arr_airport)->country) }}" src="{{ public_asset('/image/flags_new/'.strtolower(optional($flight->arr_airport)->country).'.png') }}" alt=""/>
<a href="{{ route('frontend.airports.show', [$flight->arr_airport_id]) }}">{{ optional($flight->arr_airport)->full_name ?? $flight->arr_airport_id }}</a>
</td>
<td class="text-center">{{ $flight->distance->local(0).' '.$units['distance'] }}</td>
<td class="text-center">{{ DB_ConvertMinutes($flight->flight_time) }}</td>
<td class="text-end">
@if(!setting('pilots.only_flights_from_current') || $flight->dpt_airport_id == $user->curr_airport_id)
{{-- Bid --}}
@if(setting('bids.allow_multiple_bids') === true || setting('bids.allow_multiple_bids') === false && count($saved) === 0)
<button class="btn btn-sm m-0 mx-1 p-0 px-1 save_flight {{ isset($saved[$flight->id]) ? 'btn-danger':'btn-success' }}"
x-id="{{ $flight->id }}"
x-saved-class="btn-danger"
type="button" title="Add/Remove Bid">
<i class="fas fa-map-marker"></i>
</button>
@endif
{{-- Simbrief --}}
@if($simbrief !== false && $flight->simbrief && $flight->simbrief->user_id === $user->id)
<a href="{{ route('frontend.simbrief.briefing', $flight->simbrief->id) }}" class="btn btn-sm m-0 mx-1 p-0 px-1 btn-secondary">
<i class="fas fa-file-pdf" title="View SimBrief OFP"></i>
</a>
@elseif($simbrief !== false && ($simbrief_bids === false || $simbrief_bids === true && isset($saved[$flight->id])))
@php
$aircraft_id = isset($saved[$flight->id]) ? App\Models\Bid::find($saved[$flight->id])->aircraft_id : null;
@endphp
<a href="{{ route('frontend.simbrief.generate') }}?flight_id={{ $flight->id }}@if($aircraft_id)&aircraft_id={{ $aircraft_id }} @endif" class="btn btn-sm m-0 mx-1 p-0 px-1 {{ isset($saved[$flight->id]) ? 'btn-success':'btn-primary' }}">
<i class="fas fa-file-pdf" title="Generate SimBrief OFP"></i>
</a>
@endif
{{-- vmsAcars Load --}}
@if($acars_plugin && isset($saved[$flight->id]))
<a href="vmsacars:bid/{{ $saved[$flight->id] }}" class="btn btn-sm m-0 mx-1 p-0 px-1 btn-warning">
<i class="fas fa-file-download" title="Load in vmsAcars"></i>
</a>
@elseif($acars_plugin)
<a href="vmsacars:flight/{{ $flight->id }}" class="btn btn-sm m-0 mx-1 p-0 px-1 btn-warning">
<i class="fas fa-file-download" title="Load in vmsAcars"></i>
</a>
@endif
@if(Theme::getSetting('pireps_manual'))
<a href="{{ route('frontend.pireps.create', ['flight_id' => $flight->id]) }}" class="btn btn-sm btn-info m-0 mx-1 p-0 px-1">
<i class="fas fa-file-upload" title="New Manual PIREP"></i>
</a>
@endif
@endif
{{-- v7 core Search Page --}}
<a href="{{ route('frontend.flights.search', ['airline_id' => $flight->airline_id, 'flight_number' => $flight->flight_number, 'dep_icao' => $flight->dpt_airport_id, 'arr_icao' => $flight->arr_airport_id]) }}" class="btn btn-sm btn-danger m-0 mx-1 p-0 px-1">
<i class="fas fa-search" title="v7 Search"></i>
</a>
</td>
</tr>
@endforeach
</table>
17 changes: 12 additions & 5 deletions Resources/views/scenery/index.blade.php
Expand Up @@ -63,6 +63,11 @@
</div>
</form>
</div>
@if($sceneries->count() > 0)
<div class="text-start mb-2">
@widget('DBasic::Map', ['source' => 'scenery'])
</div>
@endif
<div class="card mb-2">
<div class="card-header p-1">
<h5 class="m-1">Flight Counts</h5>
Expand All @@ -87,11 +92,13 @@
Only active and visible flights are considered.
</div>
</div>
@if($sceneries->count() > 0)
<div class="text-start mb-2">
@widget('DBasic::Map', ['source' => 'scenery'])
</div>
@endif
<div class="text-start mb-2">
@if(!setting('pilots.only_flights_from_current'))
<a href="{{ route('DBasic.scenery.flights', ['type' => 'departures']) }}" class="btn btn-sm btn-warning px-1 py-0">Search Departure Flights</a>
@endif
<a href="{{ route('DBasic.scenery.flights', ['type' => 'arrivals']) }}" class="btn btn-sm btn-warning px-1 py-0">Search Arrival Flights</a>
<a href="{{ route('DBasic.scenery.flights', ['type' => 'trips']) }}" class="btn btn-sm btn-warning px-1 py-0">Search Round Trip Flights</a>
</div>
@if(count($user_regs) > 1)
<div class="text-end mb-2">
@foreach($user_regs as $reg)
Expand Down

0 comments on commit 2d4aabd

Please sign in to comment.