User can add/edit flights

This commit is contained in:
2026-04-12 20:34:22 +10:00
parent 0f84ec023e
commit a9aa65f0d2
12 changed files with 266 additions and 20 deletions
+132 -1
View File
@@ -3,10 +3,39 @@
namespace App\Http\Controllers;
use App\Models\Airline;
use App\Models\Airport;
use App\Models\FlightClass;
use App\Models\FlightReason;
use App\Models\SeatType;
use App\Models\UserFlight;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Inertia\Inertia;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class FlightController extends Controller
{
use AuthorizesRequests;
public function rules(): array
{
return [
'flight_number' => ['nullable', 'string', 'max:10'],
'departure_date' => ['required', 'date'],
'arrival_date' => ['required', 'date', 'after:departure_date'],
'from_id' => ['required', 'integer', 'exists:airports,id'],
'to_id' => ['required', 'integer', 'exists:airports,id'],
'airline_id' => ['nullable', 'integer', 'exists:airlines,id'],
'aircraft_id' => ['nullable', 'integer', 'exists:aircraft,id'],
'aircraft_registration' => ['nullable', 'string', 'max:10'],
'seat_number' => ['nullable', 'string', 'max:10'],
'seat_type_id' => ['nullable', 'integer', 'exists:seat_types,id'],
'flight_class_id' => ['nullable', 'integer', 'exists:flight_classes,id'],
'flight_reason_id' => ['nullable', 'integer', 'exists:flight_reasons,id'],
'note' => ['nullable', 'string', 'max:5000'],
'auto_update' => ['boolean'],
];
}
public function lookup(Request $request)
{
$number = strtoupper(trim($request->query('number', '')));
@@ -28,4 +57,106 @@ class FlightController extends Controller
'aircraft_options' => [],
]);
}
private function convertedDates(array $validated): array
{
$departureAirport = Airport::find($validated['from_id']);
$arrivalAirport = Airport::find($validated['to_id']);
return [
Carbon::createFromFormat('Y-m-d\TH:i', $validated['departure_date'], $departureAirport->timezone)->utc(),
Carbon::createFromFormat('Y-m-d\TH:i', $validated['arrival_date'], $arrivalAirport->timezone)->utc(),
];
}
private function flightPayload(array $validated): array
{
[$departureUtc, $arrivalUtc] = $this->convertedDates($validated);
return [
'departure_date' => $departureUtc,
'arrival_date' => $arrivalUtc,
'flight_number' => $validated['flight_number'],
'departure_airport_id' => $validated['from_id'],
'arrival_airport_id' => $validated['to_id'],
'airline_id' => $validated['airline_id'],
'aircraft_id' => $validated['aircraft_id'],
'aircraft_registration' => $validated['aircraft_registration'],
'seat_number' => $validated['seat_number'],
'seat_type_id' => $validated['seat_type_id'],
'flight_class_id' => $validated['flight_class_id'],
'flight_reason_id' => $validated['flight_reason_id'],
'note' => $validated['note'],
'auto_update' => $validated['auto_update'],
];
}
public function store(Request $request)
{
$validated = $request->validate($this->rules());
auth()->user()->flights()->create($this->flightPayload($validated));
return redirect()->route('dashboard', Auth::user()->name);
}
public function update(Request $request, UserFlight $flight)
{
$this->authorize('update', $flight);
$validated = $request->validate($this->rules());
$flight->update($this->flightPayload($validated));
return redirect()->route('dashboard', Auth::user()->name);
}
public function add(){
return Inertia::render('AddFlight', [
'seat_types' => SeatType::all()->map(fn ($s) => ['value' => $s->id, 'title' => $s->name]),
'flight_reasons' => FlightReason::all()->map(fn ($f) => ['value' => $f->id, 'title' => $f->name]),
'flight_classes' => FlightClass::all()->map(fn ($f) => ['value' => $f->id, 'title' => $f->name]),
]);
}
public function edit(UserFlight $flight)
{
$this->authorize('update', $flight);
$flight->load('airline', 'aircraft', 'departureAirport.region.country', 'arrivalAirport.region.country', 'seatType', 'flightClass', 'flightReason');
$flightData = [
'id' => $flight->id,
'flight_number' => $flight->flight_number,
'departure_date' => $flight->departure_date->setTimezone($flight->departureAirport->timezone)->format('Y-m-d\TH:i'),
'arrival_date' => $flight->arrival_date->setTimezone($flight->arrivalAirport->timezone)->format('Y-m-d\TH:i'),
'aircraft_registration' => $flight->aircraft_registration,
'seat_number' => $flight->seat_number,
'note' => $flight->note,
'auto_update' => $flight->auto_update,
'seat_type' => $flight->seatType
? ['value' => $flight->seatType->id, 'title' => $flight->seatType->name]
: null,
'flight_class' => $flight->flightClass
? ['value' => $flight->flightClass->id, 'title' => $flight->flightClass->name]
: null,
'flight_reason' => $flight->flightReason
? ['value' => $flight->flightReason->id, 'title' => $flight->flightReason->name]
: null,
'airline_options' => $flight->airline
? [['value' => $flight->airline->id, 'title' => $flight->airline->name]]
: [],
'from_options' => [['value' => $flight->departureAirport->id, 'title' => $flight->departureAirport->name, 'country_code' => strtolower($flight->departureAirport->region->country->code)]],
'to_options' => [['value' => $flight->arrivalAirport->id, 'title' => $flight->arrivalAirport->name, 'country_code' => strtolower($flight->arrivalAirport->region->country->code)]],
'aircraft_options' => $flight->aircraft
? [['value' => $flight->aircraft->id, 'title' => $flight->aircraft->name]]
: [],
];
return Inertia::render('AddFlight', [
'flight' => $flightData,
'seat_types' => SeatType::all()->map(fn($t) => ['value' => $t->id, 'title' => $t->name]),
'flight_classes' => FlightClass::all()->map(fn($t) => ['value' => $t->id, 'title' => $t->name]),
'flight_reasons' => FlightReason::all()->map(fn($t) => ['value' => $t->id, 'title' => $t->name]),
]);
}
}
@@ -38,11 +38,20 @@ class FlightImportController extends Controller
preg_match('/\((\w+)\)/', $aircraftQuery, $matches);
$designator = $matches[1] ?? null;
$sortOverrides = [
'B788' => "CASE WHEN model_full_name ILIKE '%BBJ%' THEN 1 ELSE 0 END",
'B789' => "CASE WHEN model_full_name ILIKE '%BBJ%' THEN 1 ELSE 0 END",
];
if(!$designator){
$aircraft = [];
} else {
$aircraft = Aircraft::when($designator, fn($query) => $query->where('designator', 'ilike', $designator))
->when(
isset($sortOverrides[$designator]),
fn($q) => $q->orderByRaw($sortOverrides[$designator])
)
->orderBy('model_full_name')
->limit(10)
->get(['id', 'manufacturer_code', 'model_full_name', 'designator'])
@@ -52,6 +61,7 @@ class FlightImportController extends Controller
])
->values()
->toArray();
}
return $aircraft;
@@ -80,6 +90,7 @@ class FlightImportController extends Controller
END
", [$iata, $icao, $iata, $icao])
->limit(10)
->orderBy('id')
->get(['id', 'name', 'municipality', 'iata_code', 'icao_code', 'region_id'])
->map(fn($a) => [
'value' => $a->id,
@@ -31,6 +31,7 @@ class FlightProfileController extends Controller
return Inertia::render('FlightProfile', [
'user' => $user,
'canEdit' => auth()->check() && auth()->id() === $user->id,
'flights' => UserFlightResource::collection($flights)->resolve(),
]);
}
@@ -34,6 +34,7 @@ class SearchController extends Controller
return Aircraft::where('designator', 'ilike', "%{$q}%")
->orWhereRaw("CONCAT(manufacturer_code, ' ', model_full_name) ilike ?", ["%{$q}%"])
->limit(200)
->orderBy('id', 'asc')
->get(['id', 'manufacturer_code', 'model_full_name', 'designator'])
->map(fn($a) => [
'value' => $a->id,