Added save functionality
This commit is contained in:
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Aircraft;
|
||||||
use App\Models\Airline;
|
use App\Models\Airline;
|
||||||
|
use App\Models\Airport;
|
||||||
use App\Models\ImportedFlight;
|
use App\Models\ImportedFlight;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -43,6 +45,64 @@ class FlightImportController extends Controller
|
|||||||
return str_pad($hours, 2, '0', STR_PAD_LEFT) . ':' . $minutes;
|
return str_pad($hours, 2, '0', STR_PAD_LEFT) . ':' . $minutes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getPossibleAircraft(string $aircraftQuery) {
|
||||||
|
preg_match('/\((\w+)\)/', $aircraftQuery, $matches);
|
||||||
|
$designator = $matches[1] ?? null;
|
||||||
|
|
||||||
|
if(!$designator){
|
||||||
|
$aircraft = [];
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$aircraft = Aircraft::when($designator, fn($query) => $query->where('designator', 'ilike', $designator))
|
||||||
|
->orderBy('model_full_name')
|
||||||
|
->limit(10)
|
||||||
|
->get(['id', 'manufacturer_code', 'model_full_name', 'designator'])
|
||||||
|
->map(fn($a) => [
|
||||||
|
'value' => $a->id,
|
||||||
|
'title' => "{$a->manufacturer_code} {$a->model_full_name} ({$a->designator})",
|
||||||
|
])
|
||||||
|
->values()
|
||||||
|
->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $aircraft;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPossibleAirports(string $airportQuery) {
|
||||||
|
preg_match('/\((\w{3})\/(\w{4})\)/', $airportQuery, $matches);
|
||||||
|
$iata = $matches[1] ?? null;
|
||||||
|
$icao = $matches[2] ?? null;
|
||||||
|
|
||||||
|
if (!$iata && !$icao) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$airports = Airport::with('region.country')
|
||||||
|
->where(function ($q) use ($iata, $icao) {
|
||||||
|
$q->where('iata_code', 'ilike', $iata)
|
||||||
|
->orWhere('icao_code', 'ilike', $icao);
|
||||||
|
})
|
||||||
|
->orderByRaw("
|
||||||
|
CASE
|
||||||
|
WHEN iata_code = ? AND icao_code = ? THEN 0
|
||||||
|
WHEN iata_code = ? THEN 1
|
||||||
|
WHEN icao_code = ? THEN 2
|
||||||
|
ELSE 3
|
||||||
|
END
|
||||||
|
", [$iata, $icao, $iata, $icao])
|
||||||
|
->limit(10)
|
||||||
|
->get(['id', 'name', 'municipality', 'iata_code', 'icao_code', 'region_id'])
|
||||||
|
->map(fn($a) => [
|
||||||
|
'value' => $a->id,
|
||||||
|
'title' => "{$a->name} ({$a->iata_code}/{$a->icao_code})",
|
||||||
|
'country_code' => strtolower($a?->region->country->code ?? ''),
|
||||||
|
])
|
||||||
|
->values()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
return $airports;
|
||||||
|
}
|
||||||
|
|
||||||
public function getPossibleAirlines(string $airlineQuery) {
|
public function getPossibleAirlines(string $airlineQuery) {
|
||||||
preg_match('/\((\w{2,3})\/(\w{3,4})\)/', $airlineQuery, $matches);
|
preg_match('/\((\w{2,3})\/(\w{3,4})\)/', $airlineQuery, $matches);
|
||||||
$iata = $matches[1] ?? null;
|
$iata = $matches[1] ?? null;
|
||||||
@@ -72,10 +132,8 @@ class FlightImportController extends Controller
|
|||||||
->values()
|
->values()
|
||||||
->toArray();
|
->toArray();
|
||||||
|
|
||||||
return [
|
|
||||||
'airline_options' => $airlines,
|
return $airlines;
|
||||||
'raw_airline' => $airlineQuery,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reconcile(Request $request)
|
public function reconcile(Request $request)
|
||||||
@@ -119,9 +177,40 @@ class FlightImportController extends Controller
|
|||||||
'flight_class' => $flightToReconcile->flight_class ?? '',
|
'flight_class' => $flightToReconcile->flight_class ?? '',
|
||||||
'seat_type' => $flightToReconcile->seat_type ?? '',
|
'seat_type' => $flightToReconcile->seat_type ?? '',
|
||||||
'flight_reason' => $flightToReconcile->flight_reason ?? '',
|
'flight_reason' => $flightToReconcile->flight_reason ?? '',
|
||||||
'airline_options' => $this->getPossibleAirlines($flightToReconcile->airline ?? '')['airline_options'],
|
'airline_options' => $this->getPossibleAirlines($flightToReconcile->airline ?? ''),
|
||||||
|
'to_options' => $this->getPossibleAirports($flightToReconcile->to ?? ''),
|
||||||
|
'from_options' => $this->getPossibleAirports($flightToReconcile->from ?? ''),
|
||||||
|
'aircraft_options' => $this->getPossibleAircraft($flightToReconcile->aircraft ?? ''),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function save(Request $request){
|
||||||
|
$validated = $request->validate([
|
||||||
|
'date' => 'required|date',
|
||||||
|
'flight_number' => 'required|string',
|
||||||
|
'from_id' => 'required|integer|exists:airports,id',
|
||||||
|
'to_id' => 'required|integer|exists:airports,id',
|
||||||
|
'dep_time' => 'nullable|date_format:H:i',
|
||||||
|
'arr_time' => 'nullable|date_format:H:i',
|
||||||
|
'duration' => 'nullable|date_format:H:i',
|
||||||
|
'airline_id' => 'nullable|integer|exists:airlines,id',
|
||||||
|
'aircraft_id' => 'nullable|integer|exists:aircraft,id',
|
||||||
|
'registration' => 'nullable|string',
|
||||||
|
'seat_number' => 'nullable|string',
|
||||||
|
'seat_type_id' => 'nullable|integer',
|
||||||
|
'flight_class_id' => 'nullable|integer',
|
||||||
|
'flight_reason_id' => 'nullable|integer',
|
||||||
|
'note' => 'nullable|string',
|
||||||
|
],[
|
||||||
|
'from_id.required' => 'Please select a departure airport.',
|
||||||
|
'to_id.required' => 'Please select an arrival airport.',
|
||||||
|
'dep_time.date_format' => 'Departure time must be in HH:MM format, i.e: 01:25',
|
||||||
|
'arr_time.date_format' => 'Arrival time must be in HH:MM format, i.e: 12:25',
|
||||||
|
'duration.date_format' => 'Must be in HH:MM format, e.g: 03:37',
|
||||||
|
]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Aircraft;
|
||||||
|
use App\Models\Airline;
|
||||||
|
use App\Models\Airport;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class SearchController extends Controller
|
||||||
|
{
|
||||||
|
public function airlines(){
|
||||||
|
$q = request('q', '');
|
||||||
|
|
||||||
|
return Airline::orderByDesc('active')
|
||||||
|
->where(function ($query) use ($q) {
|
||||||
|
$query->where('name', 'ilike', "%{$q}%")
|
||||||
|
->orWhere('IATA_code', 'ilike', "%{$q}%")
|
||||||
|
->orWhere('ICAO_code', 'ilike', "%{$q}%");
|
||||||
|
})
|
||||||
|
->limit(15)
|
||||||
|
->get(['id', 'name', 'IATA_code', 'ICAO_code', 'logo'])
|
||||||
|
->map(fn($a) => [
|
||||||
|
'value' => $a->id,
|
||||||
|
'title' => "{$a->name} ({$a->IATA_code}/{$a->ICAO_code})",
|
||||||
|
])
|
||||||
|
->values();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function aircraft()
|
||||||
|
{
|
||||||
|
$q = request('q', '');
|
||||||
|
|
||||||
|
return Aircraft::where('designator', 'ilike', "%{$q}%")
|
||||||
|
->orWhereRaw("CONCAT(manufacturer_code, ' ', model_full_name) ilike ?", ["%{$q}%"])
|
||||||
|
->limit(15)
|
||||||
|
->get(['id', 'manufacturer_code', 'model_full_name', 'designator'])
|
||||||
|
->map(fn($a) => [
|
||||||
|
'value' => $a->id,
|
||||||
|
'title' => "{$a->manufacturer_code} {$a->model_full_name} ({$a->designator})",
|
||||||
|
])
|
||||||
|
->values();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function airports()
|
||||||
|
{
|
||||||
|
$q = request('q', '');
|
||||||
|
$len = strlen($q);
|
||||||
|
|
||||||
|
if ($len < 3) return [];
|
||||||
|
|
||||||
|
return Airport::with('region.country')
|
||||||
|
->when($len === 3, fn($query) => $query->where('iata_code', 'ilike', $q))
|
||||||
|
->when($len >= 4, fn($query) => $query->where(function ($sub) use ($q, $len) {
|
||||||
|
$sub->when($len === 4, fn($s) => $s->where('icao_code', 'ilike', $q))
|
||||||
|
->orWhere('name', 'ilike', "%{$q}%")
|
||||||
|
->orWhere('municipality', 'ilike', "%{$q}%");
|
||||||
|
})->orderByRaw("
|
||||||
|
CASE
|
||||||
|
WHEN icao_code = ? THEN 0
|
||||||
|
WHEN iata_code = ? THEN 1
|
||||||
|
ELSE 2
|
||||||
|
END
|
||||||
|
", [$q, $q]))
|
||||||
|
->limit(15)
|
||||||
|
->get(['id', 'name', 'municipality', 'iata_code', 'icao_code', 'region_id'])
|
||||||
|
->map(fn($a) => [
|
||||||
|
'value' => $a->id,
|
||||||
|
'title' => "{$a->name} ({$a->iata_code}/{$a->icao_code})",
|
||||||
|
'country_code' => strtolower($a->region->country->code),
|
||||||
|
])
|
||||||
|
->values();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,5 +24,6 @@ class Airline extends Model
|
|||||||
'active' => 'boolean',
|
'active' => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+7
@@ -6,6 +6,7 @@
|
|||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdi/font": "^7.4.47",
|
"@mdi/font": "^7.4.47",
|
||||||
|
"flag-icons": "^7.5.0",
|
||||||
"vuetify": "^4.0.5"
|
"vuetify": "^4.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -2703,6 +2704,12 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/flag-icons": {
|
||||||
|
"version": "7.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/flag-icons/-/flag-icons-7.5.0.tgz",
|
||||||
|
"integrity": "sha512-kd+MNXviFIg5hijH766tt+3x76ele1AXlo4zDdCxIvqWZhKt4T83bOtxUOOMlTx/EcFdUMH5yvQgYlFh1EqqFg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.15.11",
|
"version": "1.15.11",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdi/font": "^7.4.47",
|
"@mdi/font": "^7.4.47",
|
||||||
|
"flag-icons": "^7.5.0",
|
||||||
"vuetify": "^4.0.5"
|
"vuetify": "^4.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
|
|
||||||
.glass {
|
.glass {
|
||||||
background: rgba(17, 24, 39, 0.2); /* --surface at 60% */
|
background: rgba(17, 24, 39, 0.2); /* --surface at 60% */
|
||||||
backdrop-filter: blur(12px) saturate(180%);
|
|
||||||
-webkit-backdrop-filter: blur(12px) saturate(180%);
|
-webkit-backdrop-filter: blur(12px) saturate(180%);
|
||||||
|
backdrop-filter: blur(12px) saturate(180%);
|
||||||
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(56, 189, 248, 0.05);
|
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(56, 189, 248, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, nextTick } from 'vue'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
prefilledOptions: { value: number, title: string }[]
|
||||||
|
errorMessages?: string[] | string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const model = defineModel<{ value: number, title: string } | null>()
|
||||||
|
|
||||||
|
const aircraftOptions = ref(props.prefilledOptions ?? [])
|
||||||
|
const autocompleteRef = ref<any>(null)
|
||||||
|
|
||||||
|
const onFocus = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
const input = autocompleteRef.value?.$el?.querySelector('input')
|
||||||
|
input?.select()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchAircraft = async (query: string) => {
|
||||||
|
if (!query || query.length < 2) {
|
||||||
|
aircraftOptions.value = props.prefilledOptions ?? []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query === model.value?.title) return
|
||||||
|
|
||||||
|
const { data } = await axios.get('/search/aircraft', { params: { q: query } })
|
||||||
|
aircraftOptions.value = data
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<v-autocomplete
|
||||||
|
ref="autocompleteRef"
|
||||||
|
v-model="model"
|
||||||
|
label="Aircraft"
|
||||||
|
:items="aircraftOptions"
|
||||||
|
:error-messages="errorMessages"
|
||||||
|
item-title="title"
|
||||||
|
@update:search="searchAircraft"
|
||||||
|
@focus="onFocus"
|
||||||
|
hint="Showing closest matches to the imported value"
|
||||||
|
placeholder="B738"
|
||||||
|
clearable
|
||||||
|
hide-no-data
|
||||||
|
return-object
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
@@ -31,7 +31,7 @@ const searchAirlines = async (query: string) => {
|
|||||||
|
|
||||||
if (query === model.value?.title) return
|
if (query === model.value?.title) return
|
||||||
|
|
||||||
const { data } = await axios.get('/airlines/search', { params: { q: query } })
|
const { data } = await axios.get('/search/airlines', { params: { q: query } })
|
||||||
airlineOptions.value = data
|
airlineOptions.value = data
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, nextTick } from 'vue'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
prefilledOptions: { value: number, title: string, country_code: string }[]
|
||||||
|
errorMessages?: string[] | string
|
||||||
|
label?: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const model = defineModel<{ value: number, title: string, country_code: string } | null>()
|
||||||
|
|
||||||
|
const airportOptions = ref(props.prefilledOptions ?? [])
|
||||||
|
const autocompleteRef = ref<any>(null)
|
||||||
|
|
||||||
|
const onFocus = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
const input = autocompleteRef.value?.$el?.querySelector('input')
|
||||||
|
input?.select()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchAirports = async (query: string) => {
|
||||||
|
if (!query || query.length < 2) {
|
||||||
|
airportOptions.value = props.prefilledOptions ?? []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query === model.value?.title) return
|
||||||
|
|
||||||
|
const { data } = await axios.get('/search/airports', { params: { q: query } })
|
||||||
|
airportOptions.value = data
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<v-autocomplete
|
||||||
|
ref="autocompleteRef"
|
||||||
|
v-model="model"
|
||||||
|
:label="label ?? 'Airport'"
|
||||||
|
:items="airportOptions"
|
||||||
|
:error-messages="errorMessages"
|
||||||
|
item-title="title"
|
||||||
|
@update:search="searchAirports"
|
||||||
|
@focus="onFocus"
|
||||||
|
hint="Search by IATA (3 letters), ICAO (4 letters), or airport/city name"
|
||||||
|
placeholder="SYD"
|
||||||
|
clearable
|
||||||
|
hide-no-data
|
||||||
|
return-object
|
||||||
|
:custom-filter="() => true"
|
||||||
|
>
|
||||||
|
<template #prepend-inner>
|
||||||
|
<span style="padding:0.5em">
|
||||||
|
<span v-if="model" :class="`fi fi-${model.country_code}`"></span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #item="{ item, props: itemProps }">
|
||||||
|
<v-list-item v-bind="itemProps">
|
||||||
|
<template #prepend>
|
||||||
|
<span style="padding-right:1em">
|
||||||
|
<span :class="`fi fi-${item.country_code}`"></span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</v-list-item>
|
||||||
|
</template>
|
||||||
|
</v-autocomplete>
|
||||||
|
</template>
|
||||||
@@ -3,6 +3,8 @@ import MainLayout from "@/Layouts/MainLayout.vue";
|
|||||||
import GlassBox from "@/Components/FlightsGoneBy/GlassBox.vue";
|
import GlassBox from "@/Components/FlightsGoneBy/GlassBox.vue";
|
||||||
import {Head, useForm} from "@inertiajs/vue3";
|
import {Head, useForm} from "@inertiajs/vue3";
|
||||||
import AirlineSearchBox from "@/Components/FlightsGoneBy/AirlineSearchBox.vue";
|
import AirlineSearchBox from "@/Components/FlightsGoneBy/AirlineSearchBox.vue";
|
||||||
|
import AircraftSearchBox from "@/Components/FlightsGoneBy/AircraftSearchBox.vue";
|
||||||
|
import AirportSearchBox from "@/Components/FlightsGoneBy/AirportSearchBox.vue";
|
||||||
|
|
||||||
defineOptions({ layout: MainLayout });
|
defineOptions({ layout: MainLayout });
|
||||||
|
|
||||||
@@ -24,6 +26,9 @@ const props = defineProps<{
|
|||||||
arr_time: string
|
arr_time: string
|
||||||
duration: string
|
duration: string
|
||||||
airline_options: { value: number, title: string }[]
|
airline_options: { value: number, title: string }[]
|
||||||
|
from_options: { value: number, title: string, country_code: string}[]
|
||||||
|
to_options: { value: number, title: string, country_code: string }[]
|
||||||
|
aircraft_options: { value: number, title: string }[]
|
||||||
}
|
}
|
||||||
}>()
|
}>()
|
||||||
const flight = props.flight;
|
const flight = props.flight;
|
||||||
@@ -31,13 +36,13 @@ const flight = props.flight;
|
|||||||
const form = useForm({
|
const form = useForm({
|
||||||
date: flight.date,
|
date: flight.date,
|
||||||
flight_number: flight.flight_number,
|
flight_number: flight.flight_number,
|
||||||
from: '',
|
from: flight.from_options[0] ?? null,
|
||||||
to: '',
|
to: flight.to_options[0] ?? null,
|
||||||
dep_time: flight.dep_time,
|
dep_time: flight.dep_time,
|
||||||
arr_time: flight.arr_time,
|
arr_time: flight.arr_time,
|
||||||
duration: flight.duration,
|
duration: flight.duration,
|
||||||
airline_id: flight.airline_options[0] ?? null,
|
airline_id: flight.airline_options[0] ?? null,
|
||||||
aircraft: '',
|
aircraft: flight.aircraft_options[0] ?? null,
|
||||||
registration: flight.registration,
|
registration: flight.registration,
|
||||||
seat_number: flight.seat_number,
|
seat_number: flight.seat_number,
|
||||||
seat_type: flight.seat_types[flight.seat_type],
|
seat_type: flight.seat_types[flight.seat_type],
|
||||||
@@ -47,8 +52,42 @@ const form = useForm({
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const submitForm = useForm({
|
||||||
|
date: '' as string | null,
|
||||||
|
flight_number: '' as string | null,
|
||||||
|
from_id: null as number | null,
|
||||||
|
to_id: null as number | null,
|
||||||
|
dep_time: '' as string | null,
|
||||||
|
arr_time: '' as string | null,
|
||||||
|
duration: '' as string | null,
|
||||||
|
airline_id: null as number | null,
|
||||||
|
aircraft_id: null as number | null,
|
||||||
|
registration: '' as string | null,
|
||||||
|
seat_number: '' as string | null,
|
||||||
|
seat_type_id: null as number | null,
|
||||||
|
flight_class_id: null as number | null,
|
||||||
|
flight_reason_id: null as number | null,
|
||||||
|
note: '' as string | null,
|
||||||
|
});
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
form.post(route('reconcile.store'));
|
submitForm.date = form.date;
|
||||||
|
submitForm.flight_number = form.flight_number;
|
||||||
|
submitForm.from_id = form.from?.value ?? null;
|
||||||
|
submitForm.to_id = form.to?.value ?? null;
|
||||||
|
submitForm.dep_time = form.dep_time;
|
||||||
|
submitForm.arr_time = form.arr_time;
|
||||||
|
submitForm.duration = form.duration;
|
||||||
|
submitForm.airline_id = form.airline_id?.value ?? null;
|
||||||
|
submitForm.aircraft_id = form.aircraft?.value ?? null;
|
||||||
|
submitForm.registration = form.registration;
|
||||||
|
submitForm.seat_number = form.seat_number;
|
||||||
|
submitForm.seat_type_id = form.seat_type?.value ?? null;
|
||||||
|
submitForm.flight_class_id = form.flight_class?.value ?? null;
|
||||||
|
submitForm.flight_reason_id = form.flight_reason?.value ?? null;
|
||||||
|
submitForm.note = form.note;
|
||||||
|
|
||||||
|
submitForm.post(route('import.save'));
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@@ -65,36 +104,47 @@ function submit() {
|
|||||||
<!-- Date / Flight Number / Registration -->
|
<!-- Date / Flight Number / Registration -->
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" md="4">
|
<v-col cols="12" md="4">
|
||||||
<v-text-field type="date" v-model="form.date" label="Date" placeholder="03-18-11" :error-messages="form.errors.date" />
|
<v-text-field type="date" v-model="form.date" label="Date" placeholder="03-18-11" :error-messages="submitForm.errors.date" />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="4">
|
<v-col cols="12" md="4">
|
||||||
<v-text-field v-model="form.flight_number" label="Flight Number" placeholder="UL227" :error-messages="form.errors.flight_number" />
|
<v-text-field v-model="form.flight_number" label="Flight Number" placeholder="UL227" :error-messages="submitForm.errors.flight_number" />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="4">
|
<v-col cols="12" md="4">
|
||||||
<v-text-field v-model="form.registration" label="Registration" placeholder="4R-ALX" :error-messages="form.errors.registration" />
|
<v-text-field v-model="form.registration" label="Registration" placeholder="4R-ALX" :error-messages="submitForm.errors.registration" />
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
<!-- From / To -->
|
<!-- From / To -->
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" md="6">
|
<v-col cols="24" md="12">
|
||||||
<v-autocomplete label="From" :items="[]" placeholder="Dubai International (DXB)" :error-messages="form.errors.from" hide-no-data clearable />
|
<AirportSearchBox
|
||||||
|
v-model="form.from"
|
||||||
|
label="From"
|
||||||
|
:prefilled-options="flight.from_options"
|
||||||
|
:error-messages="submitForm.errors.from_id"
|
||||||
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="6">
|
</v-row>
|
||||||
<v-autocomplete label="To" :items="[]" placeholder="Kuwait (KWI)" :error-messages="form.errors.to" hide-no-data clearable />
|
<v-row>
|
||||||
|
<v-col cols="24" md="12">
|
||||||
|
<AirportSearchBox
|
||||||
|
label="To"
|
||||||
|
v-model="form.to"
|
||||||
|
:prefilled-options="flight.to_options"
|
||||||
|
:error-messages="submitForm.errors.to_id"
|
||||||
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
<!-- Dep time / Arr time / Duration -->
|
<!-- Dep time / Arr time / Duration -->
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" md="4">
|
<v-col cols="12" md="4">
|
||||||
<v-text-field v-model="form.dep_time" type="time" label="Departure Time" placeholder="09:30" :error-messages="form.errors.dep_time" />
|
<v-text-field v-model="form.dep_time" type="time" label="Departure Time" placeholder="09:30" :error-messages="submitForm.errors.dep_time" />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="4">
|
<v-col cols="12" md="4">
|
||||||
<v-text-field v-model="form.arr_time" type="time" label="Arrival Time" placeholder="11:45" :error-messages="form.errors.arr_time" />
|
<v-text-field v-model="form.arr_time" type="time" label="Arrival Time" placeholder="11:45" :error-messages="submitForm.errors.arr_time" />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="4">
|
<v-col cols="12" md="4">
|
||||||
<v-text-field v-model="form.duration" label="Duration" placeholder="1:23" :error-messages="form.errors.duration" />
|
<v-text-field v-model="form.duration" label="Duration" placeholder="1:23" :error-messages="submitForm.errors.duration" />
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
@@ -104,35 +154,39 @@ function submit() {
|
|||||||
<AirlineSearchBox
|
<AirlineSearchBox
|
||||||
v-model="form.airline_id"
|
v-model="form.airline_id"
|
||||||
:prefilled-options="flight.airline_options"
|
:prefilled-options="flight.airline_options"
|
||||||
:error-messages="form.errors.airline_id"
|
:error-messages="submitForm.errors.airline_id"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="6">
|
<v-col cols="12" md="6">
|
||||||
<v-autocomplete label="Aircraft" :items="[]" placeholder="Airbus A330" :error-messages="form.errors.aircraft" hide-no-data clearable />
|
<AircraftSearchBox
|
||||||
|
v-model="form.aircraft"
|
||||||
|
:prefilled-options="flight.aircraft_options"
|
||||||
|
:error-messages="submitForm.errors.aircraft_id"
|
||||||
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
<!-- Seat Number / Seat Type / Flight Class / Flight Reason -->
|
<!-- Seat Number / Seat Type / Flight Class / Flight Reason -->
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" md="3">
|
<v-col cols="12" md="3">
|
||||||
<v-text-field v-model="form.seat_number" label="Seat Number" placeholder="22A" :error-messages="form.errors.seat_number" />
|
<v-text-field v-model="form.seat_number" label="Seat Number" placeholder="22A" :error-messages="submitForm.errors.seat_number" />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="3">
|
<v-col cols="12" md="3">
|
||||||
<v-select v-model="form.seat_type" label="Seat Type" :items="flight.seat_types" :error-messages="form.errors.seat_type" clearable />
|
<v-select v-model="form.seat_type" label="Seat Type" :items="flight.seat_types" :error-messages="submitForm.errors.seat_type_id" clearable />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="3">
|
<v-col cols="12" md="3">
|
||||||
<v-select v-model="form.flight_class" label="Class" :items="flight.flight_classes" :error-messages="form.errors.flight_class" clearable />
|
<v-select v-model="form.flight_class" label="Class" :items="flight.flight_classes" :error-messages="submitForm.errors.flight_class_id" clearable />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="12" md="3">
|
<v-col cols="12" md="3">
|
||||||
<v-select v-model="form.flight_reason" label="Reason" :items="flight.flight_reasons" :error-messages="form.errors.flight_reason" clearable />
|
<v-select v-model="form.flight_reason" label="Reason" :items="flight.flight_reasons" :error-messages="submitForm.errors.flight_reason_id" clearable />
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
<!-- Note -->
|
<!-- Note -->
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12">
|
<v-col cols="12">
|
||||||
<v-textarea v-model="form.note" label="Note" placeholder="Any additional notes…" :error-messages="form.errors.note" rows="3" auto-grow />
|
<v-textarea v-model="form.note" label="Note" placeholder="Any additional notes…" :error-messages="submitForm.errors.note" rows="3" auto-grow />
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { ZiggyVue } from '../../vendor/tightenco/ziggy';
|
|||||||
import { createApp, h, DefineComponent } from 'vue';
|
import { createApp, h, DefineComponent } from 'vue';
|
||||||
import vuetify from './plugins/vuetify';
|
import vuetify from './plugins/vuetify';
|
||||||
import '@mdi/font/css/materialdesignicons.css'
|
import '@mdi/font/css/materialdesignicons.css'
|
||||||
|
import 'flag-icons/css/flag-icons.min.css'
|
||||||
|
|
||||||
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
|
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
|
||||||
|
|
||||||
|
|||||||
+8
-18
@@ -3,6 +3,7 @@
|
|||||||
use App\Http\Controllers\FlightImportController;
|
use App\Http\Controllers\FlightImportController;
|
||||||
use App\Http\Controllers\LogoController;
|
use App\Http\Controllers\LogoController;
|
||||||
use App\Http\Controllers\ProfileController;
|
use App\Http\Controllers\ProfileController;
|
||||||
|
use App\Http\Controllers\SearchController;
|
||||||
use App\Models\Airline;
|
use App\Models\Airline;
|
||||||
use Illuminate\Foundation\Application;
|
use Illuminate\Foundation\Application;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
@@ -43,24 +44,6 @@ Route::domain(config('app.domain'))->group(
|
|||||||
})->name('reconcile');
|
})->name('reconcile');
|
||||||
|
|
||||||
|
|
||||||
Route::get('/airlines/search', function () {
|
|
||||||
$q = request('q', '');
|
|
||||||
|
|
||||||
return Airline::orderByDesc('active')
|
|
||||||
->where(function ($query) use ($q) {
|
|
||||||
$query->where('name', 'ilike', "%{$q}%")
|
|
||||||
->orWhere('IATA_code', 'ilike', "%{$q}%")
|
|
||||||
->orWhere('ICAO_code', 'ilike', "%{$q}%");
|
|
||||||
})
|
|
||||||
->limit(15)
|
|
||||||
->get(['id', 'name', 'IATA_code', 'ICAO_code', 'logo'])
|
|
||||||
->map(fn($a) => [
|
|
||||||
'value' => $a->id,
|
|
||||||
'title' => "{$a->name} ({$a->IATA_code}/{$a->ICAO_code})",
|
|
||||||
])
|
|
||||||
->values();
|
|
||||||
})->name('airlines.search');
|
|
||||||
|
|
||||||
Route::post('/flights/import', [FlightImportController::class, 'store'])->name('flights.import.store');
|
Route::post('/flights/import', [FlightImportController::class, 'store'])->name('flights.import.store');
|
||||||
|
|
||||||
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
|
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
|
||||||
@@ -68,6 +51,13 @@ Route::domain(config('app.domain'))->group(
|
|||||||
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
|
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::post('/import/save', [FlightImportController::class, 'save'])->name('import.save');
|
||||||
|
|
||||||
|
//Search Routes
|
||||||
|
Route::get('/search/airlines', [SearchController::class, 'airlines'])->name('search.airlines');
|
||||||
|
Route::get('/search/aircraft', [SearchController::class, 'aircraft'])->name('search.aircraft');
|
||||||
|
Route::get('/search/airports', [SearchController::class, 'airports'])->name('search.airports');
|
||||||
|
|
||||||
require __DIR__.'/auth.php';
|
require __DIR__.'/auth.php';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user