From 5ac580bb068d70ce70ff2374de08ab6ead9308dc Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 11 Jul 2026 18:44:40 +1000 Subject: [PATCH] v1 Release --- .../GetAircraftInfoForArrivedFlights.php | 2 + .../Controllers/UserProfileController.php | 1 - app/Models/UserFlight.php | 51 +++++++---- .../FlightsGoneBy/AircraftToolTip.vue | 6 +- .../Components/FlightsGoneBy/FlightFilter.vue | 24 ++++- .../js/Components/FlightsGoneBy/FlightMap.vue | 89 ++++++++++++------- .../FlightsGoneBy/FlightToolTip.vue | 6 +- .../Liveries/LiveryAttribution.vue | 21 +++++ .../{ => Liveries}/LiveryImage.vue | 7 +- .../FlightsGoneBy/Panels/AircraftPanel.vue | 2 +- .../FlightsGoneBy/Panels/RoutePanel.vue | 2 +- .../fun_challenges.airport_alphabet.vue | 7 +- resources/js/Pages/UserFlight.vue | 5 +- resources/js/Pages/UserProfile.vue | 10 ++- resources/js/Types/types.d.ts | 10 ++- 15 files changed, 171 insertions(+), 72 deletions(-) create mode 100644 resources/js/Components/FlightsGoneBy/Liveries/LiveryAttribution.vue rename resources/js/Components/FlightsGoneBy/{ => Liveries}/LiveryImage.vue (57%) diff --git a/app/Console/Commands/GetAircraftInfoForArrivedFlights.php b/app/Console/Commands/GetAircraftInfoForArrivedFlights.php index 03c95ac..f1d8fd4 100644 --- a/app/Console/Commands/GetAircraftInfoForArrivedFlights.php +++ b/app/Console/Commands/GetAircraftInfoForArrivedFlights.php @@ -129,10 +129,12 @@ class GetAircraftInfoForArrivedFlights extends Command if ($data->estimated_departure_utc?->ne($originalDeparture)) { $updates['departure_date'] = $data->estimated_departure_utc; + $updates['departure_processed_at'] = $data->estimated_departure_utc; } if ($data->estimated_arrival_utc?->ne($originalArrival)) { $updates['arrival_date'] = $data->estimated_arrival_utc; + $updates['arrival_processed_at'] = $data->estimated_arrival_utc; } if ($data->equipment_iata && $originalAircraft?->iata_code !== $data->equipment_iata) { diff --git a/app/Http/Controllers/UserProfileController.php b/app/Http/Controllers/UserProfileController.php index 2a5ed0c..c55c5bc 100644 --- a/app/Http/Controllers/UserProfileController.php +++ b/app/Http/Controllers/UserProfileController.php @@ -93,7 +93,6 @@ class UserProfileController extends Controller 'canView' => Gate::allows('viewProfileData', $user), 'user' => $user, 'followStatus' => auth()->check() ? auth()->user()->followStatus($user) : 'none', - 'otherUsersOnFlight' => $userFlight->otherUsersOnFlight(), ]); } diff --git a/app/Models/UserFlight.php b/app/Models/UserFlight.php index e67a0ac..0f4a584 100644 --- a/app/Models/UserFlight.php +++ b/app/Models/UserFlight.php @@ -55,11 +55,12 @@ class UserFlight extends Model 'duration', 'duration_display', 'distance', - 'livery_url', + 'livery', 'scope', 'range', 'region_range', - 'class_seat_combined' + 'class_seat_combined', + 'other_users_on_flight' ]; protected static function booted(): void @@ -207,19 +208,23 @@ class UserFlight extends Model return !$this->isDomestic(); } - public function otherUsersOnFlight(): Collection + protected function otherUsersOnFlight(): Attribute { - return UserFlight::where('user_id', '!=', $this->user_id) - ->where('departure_airport_id', $this->departure_airport_id) - ->where('arrival_airport_id', $this->arrival_airport_id) - ->where('flight_number', $this->flight_number) - ->where('airline_id', $this->airline_id) - ->whereRaw('DATE(departure_date AT TIME ZONE \'UTC\') = ?', [ - Carbon::parse($this->departure_date)->utc()->toDateString() - ]) - ->with('user') - ->get() - ->pluck('user.name'); + return Attribute::make( + get: function () { + return once(fn() => UserFlight::where('user_id', '!=', $this->user_id) + ->where('departure_airport_id', $this->departure_airport_id) + ->where('arrival_airport_id', $this->arrival_airport_id) + ->where('flight_number', $this->flight_number) + ->where('airline_id', $this->airline_id) + ->whereRaw('DATE(departure_date AT TIME ZONE \'UTC\') = ?', [ + Carbon::parse($this->departure_date)->utc()->toDateString() + ]) + ->with('user') + ->get() + ->pluck('user.name')); + } + ); } public static function snapshot($userFlightId): array @@ -286,16 +291,19 @@ class UserFlight extends Model return $this->belongsTo(FlightReason::class); } - public function liveryUrl(): Attribute{ + public function livery(): Attribute{ return Attribute::make( get: function () { - $user = auth()?->user(); $useAi = !$user || $user->getSetting('ai_liveries'); $apiUrl = config('app.logo_api_url'); + $attribution = ''; + $attributionUrl = ''; + $isAi = false; + if (!$this->aircraft) { return null; } @@ -305,6 +313,8 @@ class UserFlight extends Model $path = "images/liveries/{$this->airline->internal_name}_{$this->aircraft->designator}.png"; if (Storage::disk('local')->exists($path)) { $finalPath = $apiUrl."/airline/{$this->airline->internal_name}/livery/{$this->aircraft->designator}"; + $attribution = 'This image is AI generated and may not be an accurate representation of the aircraft.'; + $isAi = true; } } @@ -312,6 +322,8 @@ class UserFlight extends Model $path = "images/livery_templates/{$this->aircraft->designator}.png"; if (Storage::disk('local')->exists($path)) { $finalPath = $apiUrl."/aircraft/{$this->aircraft->designator}/livery"; + $attribution = '© NoRebbo Blank Aircraft Templates'; + $attributionUrl = 'https://www.norebbo.com/category/aircraft-templates/'; } } @@ -319,7 +331,12 @@ class UserFlight extends Model return null; } - return $finalPath; + return [ + 'image_url' => $finalPath, + 'attribution' => $attribution, + 'attribution_url' => $attributionUrl, + 'is_ai' => $isAi, + ]; } ); } diff --git a/resources/js/Components/FlightsGoneBy/AircraftToolTip.vue b/resources/js/Components/FlightsGoneBy/AircraftToolTip.vue index 3c6c907..038c861 100644 --- a/resources/js/Components/FlightsGoneBy/AircraftToolTip.vue +++ b/resources/js/Components/FlightsGoneBy/AircraftToolTip.vue @@ -3,7 +3,7 @@ import {Aircraft, Airline, Flight} from "@/Types/types"; import GlassTooltip from "@/Components/FlightsGoneBy/GlassTooltip.vue"; import InlineBadge from "@/Components/FlightsGoneBy/InlineBadge.vue"; import WakeTurbulence from "@/Components/FlightsGoneBy/WakeTurbulence.vue"; -import LiveryImage from "@/Components/FlightsGoneBy/LiveryImage.vue"; +import LiveryImage from "@/Components/FlightsGoneBy/Liveries/LiveryImage.vue"; import ToolTipDivider from "@/Components/FlightsGoneBy/Tooltips/ToolTipDivider.vue"; import ToolTipRows from "@/Components/FlightsGoneBy/Tooltips/ToolTipRows.vue"; import ToolTipRow from "@/Components/FlightsGoneBy/Tooltips/ToolTipRow.vue"; @@ -50,8 +50,8 @@ function formatEngineType(type: string): string { - - + + diff --git a/resources/js/Components/FlightsGoneBy/FlightFilter.vue b/resources/js/Components/FlightsGoneBy/FlightFilter.vue index f9e98c5..87086cf 100644 --- a/resources/js/Components/FlightsGoneBy/FlightFilter.vue +++ b/resources/js/Components/FlightsGoneBy/FlightFilter.vue @@ -24,6 +24,7 @@ const emit = defineEmits<{ manufacturers: string[] aircraftModels: number[] airportRegions: number[] + otherUsers: string[] }] }>() @@ -62,10 +63,11 @@ function buildOptions(flights: Flight[]) { const manufacturers = new Map() const aircraftModels = new Map() const airportRegions = new Map }>() + const otherUsers = new Set() flights.forEach(f => { years.add(new Date(f.departure_date).getFullYear()) - + f.other_users_on_flight?.forEach(name => otherUsers.add(name)) if (f.airline) { airlines.set(f.airline.id, { id: f.airline.id, name: f.airline.name, airline: f.airline }) @@ -143,6 +145,7 @@ function buildOptions(flights: Flight[]) { manufacturers: [...manufacturers.values()].sort((a, b) => a.name.localeCompare(b.name)), aircraftModels: [...aircraftModels.values()].sort((a, b) => a.name.localeCompare(b.name)), airportRegions: [...airportRegions.values()].sort((a, b) => a.name.localeCompare(b.name)), + otherUsers: [...otherUsers].sort((a, b) => a.localeCompare(b)), } } @@ -165,6 +168,7 @@ const selectedSeatTypes = ref([]) const selectedManufacturers = ref([]) const selectedAircraftModels = ref([]) const selectedAirportRegions = ref([]) +const selectedOtherUsers = ref([]) // When selected countries change, drop any selected regions that no longer // belong to any of the selected countries. @@ -194,6 +198,7 @@ function emitFilters() { manufacturers: selectedManufacturers.value, aircraftModels: selectedAircraftModels.value, airportRegions: selectedAirportRegions.value, + otherUsers: selectedOtherUsers.value, }) } @@ -508,7 +513,22 @@ const countryFlagClass = (code: string) => +{{ selectedCrewTypes.length - 2 }} - + + + diff --git a/resources/js/Components/FlightsGoneBy/FlightMap.vue b/resources/js/Components/FlightsGoneBy/FlightMap.vue index a88321e..7cb5105 100644 --- a/resources/js/Components/FlightsGoneBy/FlightMap.vue +++ b/resources/js/Components/FlightsGoneBy/FlightMap.vue @@ -1,43 +1,46 @@ + + + + diff --git a/resources/js/Components/FlightsGoneBy/LiveryImage.vue b/resources/js/Components/FlightsGoneBy/Liveries/LiveryImage.vue similarity index 57% rename from resources/js/Components/FlightsGoneBy/LiveryImage.vue rename to resources/js/Components/FlightsGoneBy/Liveries/LiveryImage.vue index e8e7f68..b3b709a 100644 --- a/resources/js/Components/FlightsGoneBy/LiveryImage.vue +++ b/resources/js/Components/FlightsGoneBy/Liveries/LiveryImage.vue @@ -1,6 +1,7 @@ @@ -18,9 +19,11 @@ defineProps<{ display:flex; flex-direction: column; justify-content: flex-end; + align-items: center; width: 100%; aspect-ratio: 16/9; background-size: cover; min-width: 300px; } + diff --git a/resources/js/Components/FlightsGoneBy/Panels/AircraftPanel.vue b/resources/js/Components/FlightsGoneBy/Panels/AircraftPanel.vue index 3b6f584..6357cc6 100644 --- a/resources/js/Components/FlightsGoneBy/Panels/AircraftPanel.vue +++ b/resources/js/Components/FlightsGoneBy/Panels/AircraftPanel.vue @@ -5,7 +5,7 @@ import DetailRow from "@/Components/FlightsGoneBy/Panels/DetailRow.vue"; import type {Flight} from "@/Types/types"; import PanelHeader from "@/Components/FlightsGoneBy/Panels/PanelHeader.vue"; import PanelSubHeader from "@/Components/FlightsGoneBy/Panels/PanelSubHeader.vue"; -import LiveryImage from "@/Components/FlightsGoneBy/LiveryImage.vue"; +import LiveryImage from "@/Components/FlightsGoneBy/Liveries/LiveryImage.vue"; defineProps<{ flight: Flight diff --git a/resources/js/Components/FlightsGoneBy/Panels/RoutePanel.vue b/resources/js/Components/FlightsGoneBy/Panels/RoutePanel.vue index 85136e5..1bf7080 100644 --- a/resources/js/Components/FlightsGoneBy/Panels/RoutePanel.vue +++ b/resources/js/Components/FlightsGoneBy/Panels/RoutePanel.vue @@ -13,7 +13,7 @@ defineProps<{