From 1d5b9f340f11c09ab5d8c5f45683aececbbadcc6 Mon Sep 17 00:00:00 2001 From: josh Date: Sat, 16 May 2026 23:48:18 +1000 Subject: [PATCH] Added Notifications --- .../Controllers/AchievementController.php | 69 +- .../Controllers/Api/UserApiController.php | 5 +- .../Controllers/FlightProfileController.php | 1 + app/Http/Controllers/UserFlightController.php | 4 +- app/Models/Achievement.php | 1 + app/Models/Aircraft.php | 26 +- app/Models/User.php | 8 + .../Achievements/AchievementService.php | 2 +- .../Achievements/Checkers/AircraftChecker.php | 30 +- .../CountriesAndContinentsChecker.php | 7 + .../Checkers/GeneralFlyingChecker.php | 5 + ..._05_16_105657_add_distance_achievement.php | 102 + resources/css/app.css | 4 + resources/js/Components/Distance.vue | 40 + .../FlightsGoneBy/AchievementCard.vue | 31 +- .../FlightsGoneBy/AirlineAlphabetTable.vue | 112 + .../FlightsGoneBy/AllianceChallenge.vue | 147 ++ .../FlightsGoneBy/AlphabetTable.vue | 115 ++ .../Components/FlightsGoneBy/BoardingPass.vue | 13 +- .../Components/FlightsGoneBy/ButtonLink.vue | 31 + .../FlightsGoneBy/DepartureBoard.vue | 3 +- .../Feed/FlightBookedFeedItem.vue | 2 +- .../Components/FlightsGoneBy/FlightBadge.vue | 30 + .../js/Components/FlightsGoneBy/FlightMap.vue | 2 +- .../FlightsGoneBy/FlightRegionTable.vue | 70 +- .../FlightsGoneBy/FlightStatsBar.vue | 18 +- .../FlightsGoneBy/FlightToolTip.vue | 1 - .../FlightsGoneBy/GenericBadgeTable.vue | 90 + .../Components/FlightsGoneBy/GlassTooltip.vue | 3 +- .../Components/FlightsGoneBy/InlineBadge.vue | 2 +- .../FlightsGoneBy/Panels/PanelSubHeader.vue | 10 +- .../FlightsGoneBy/ProfileHeader.vue | 18 +- .../FlightsGoneBy/ProfileLayout.vue | 2 +- resources/js/Components/FormattedNumber.vue | 20 + resources/js/Components/Maps/Brazil.vue | 1811 +++++++++++++++++ .../js/Composables/useAircraftFamilies.ts | 51 + .../js/Composables/useAlphabetAirlines.ts | 43 + .../js/Composables/useAlphabetFlights.ts | 81 + resources/js/Composables/useContinentPairs.ts | 164 ++ resources/js/Composables/useFlightStats.ts | 28 - resources/js/Composables/useFlights.ts | 6 +- resources/js/Composables/useRegionFlights.ts | 10 +- .../Achievements/aircraft.all_airbus_a3xx.vue | 101 + .../Achievements/aircraft.all_boeing_7x7.vue | 90 + .../airlines_alliances.all_oneworld.vue | 29 + .../airlines_alliances.all_skyteam.vue | 29 + .../airlines_alliances.all_star_alliance.vue | 29 + ...irlines_alliances.all_vanilla_alliance.vue | 28 + ...ntinents.all_continent_pairs_both_ways.vue | 83 + ...continents.all_continent_pairs_one_way.vue | 91 + .../fun_challenges.airline_alphabet.vue | 278 +++ .../fun_challenges.airport_alphabet.vue | 280 +++ .../fun_challenges.australian_states.vue | 8 +- .../fun_challenges.brazilian_states.vue | 67 + .../fun_challenges.canadian_provinces.vue | 5 +- .../fun_challenges.chinese_provinces.vue | 1 - .../Achievements/fun_challenges.us_states.vue | 1 - .../js/Pages/Profile/UserAchievement.vue | 39 +- resources/js/Pages/UserFlight.vue | 5 +- resources/js/Pages/UserProfile.vue | 3 +- resources/js/Types/types.d.ts | 1 + 61 files changed, 4204 insertions(+), 182 deletions(-) create mode 100644 database/migrations/2026_05_16_105657_add_distance_achievement.php create mode 100644 resources/js/Components/Distance.vue create mode 100644 resources/js/Components/FlightsGoneBy/AirlineAlphabetTable.vue create mode 100644 resources/js/Components/FlightsGoneBy/AllianceChallenge.vue create mode 100644 resources/js/Components/FlightsGoneBy/AlphabetTable.vue create mode 100644 resources/js/Components/FlightsGoneBy/ButtonLink.vue create mode 100644 resources/js/Components/FlightsGoneBy/FlightBadge.vue create mode 100644 resources/js/Components/FlightsGoneBy/GenericBadgeTable.vue create mode 100644 resources/js/Components/FormattedNumber.vue create mode 100644 resources/js/Components/Maps/Brazil.vue create mode 100644 resources/js/Composables/useAircraftFamilies.ts create mode 100644 resources/js/Composables/useAlphabetAirlines.ts create mode 100644 resources/js/Composables/useAlphabetFlights.ts create mode 100644 resources/js/Composables/useContinentPairs.ts create mode 100644 resources/js/Pages/Profile/Achievements/aircraft.all_airbus_a3xx.vue create mode 100644 resources/js/Pages/Profile/Achievements/aircraft.all_boeing_7x7.vue create mode 100644 resources/js/Pages/Profile/Achievements/airlines_alliances.all_oneworld.vue create mode 100644 resources/js/Pages/Profile/Achievements/airlines_alliances.all_skyteam.vue create mode 100644 resources/js/Pages/Profile/Achievements/airlines_alliances.all_star_alliance.vue create mode 100644 resources/js/Pages/Profile/Achievements/airlines_alliances.all_vanilla_alliance.vue create mode 100644 resources/js/Pages/Profile/Achievements/countries_continents.all_continent_pairs_both_ways.vue create mode 100644 resources/js/Pages/Profile/Achievements/countries_continents.all_continent_pairs_one_way.vue create mode 100644 resources/js/Pages/Profile/Achievements/fun_challenges.airline_alphabet.vue create mode 100644 resources/js/Pages/Profile/Achievements/fun_challenges.airport_alphabet.vue create mode 100644 resources/js/Pages/Profile/Achievements/fun_challenges.brazilian_states.vue diff --git a/app/Http/Controllers/AchievementController.php b/app/Http/Controllers/AchievementController.php index be5c780..7671809 100644 --- a/app/Http/Controllers/AchievementController.php +++ b/app/Http/Controllers/AchievementController.php @@ -3,6 +3,9 @@ namespace App\Http\Controllers; use App\Models\Achievement; +use App\Models\Aircraft; +use App\Models\Alliance; +use App\Models\Continent; use App\Models\Country; use App\Models\User; use Illuminate\Http\Request; @@ -15,7 +18,7 @@ class AchievementController extends Controller $achievements = Achievement::with(['category', 'difficulty']) ->get() ->groupBy(fn(Achievement $a) => $a->category->name) - ->map(fn($group) => $group->sortBy('id')->values()); + ->map(fn($group) => $group->sortBy('sort_order')->values()); $userAchievements = $user->achievements() ->with('achievement') @@ -29,26 +32,72 @@ class AchievementController extends Controller 'isFollowing' => auth()->check() && auth()->user()->isFollowing($user), 'achievements' => $achievements, 'userAchievements' => $userAchievements, + 'loggedInUser' => auth()->user(), ]); } + function getRegionsByCountryCode(string $countryCode) + { + return Country::whereCode($countryCode) + ->first() + ->regions() + ->orderBy('name') + ->get() + ->toArray(); + } + public function specific(User $user, Achievement $achievement) { $regions = match($achievement->internal_name){ - 'fun_challenges.australian_states' => Country::where('code', 'AU')->first()->regions->toArray(), - 'fun_challenges.chinese_provinces' => Country::where('code', 'CN')->first()->regions->toArray(), - 'fun_challenges.canadian_provinces' => Country::where('code', 'CA')->first()->regions->toArray(), - 'fun_challenges.us_states' => Country::where('code', 'US')->first()->regions->toArray(), + 'fun_challenges.australian_states' => $this->getRegionsByCountryCode('AU'), + 'fun_challenges.chinese_provinces' => $this->getRegionsByCountryCode('CN'), + 'fun_challenges.canadian_provinces' => $this->getRegionsByCountryCode('CA'), + 'fun_challenges.brazilian_states' => $this->getRegionsByCountryCode('BR'), + 'fun_challenges.us_states' => $this->getRegionsByCountryCode('US'), + default => [], + }; + + $allianceInternalName = match($achievement->internal_name){ + 'airlines_alliances.all_star_alliance' => 'star_alliance', + 'airlines_alliances.all_oneworld' => 'oneworld', + 'airlines_alliances.all_skyteam' => 'skyteam', + 'airlines_alliances.all_vanilla_alliance' => 'vanilla_alliance', + default => null, + }; + + $continents = match($achievement->internal_name){ + 'countries_continents.all_continent_pairs_one_way', 'countries_continents.all_continent_pairs_both_ways' => Continent::all()->toArray(), + default => [], + }; + + $alliance = null; + $airlines = []; + + if ($allianceInternalName) { + $alliance = Alliance::where('internal_name', $allianceInternalName) + ->with('airlines') + ->firstOrFail(); + $airlines = $alliance->airlines()->with('country')->orderBy('name')->get(); + } + + $aircraftFamilies = match($achievement->internal_name){ + 'aircraft.all_boeing_7x7' => Aircraft::BOEING_FAMILIES, + 'aircraft.all_airbus_a3xx' => Aircraft::AIRBUS_FAMILIES, default => [], }; return Inertia::render('Profile/UserAchievement', [ - 'user' => $user, - 'achievement' => $achievement, + 'user' => $user, + 'achievement' => $achievement, + 'loggedInUser' => auth()->user(), 'userAchievement' => $user->achievements()->where('achievement_id', $achievement->id)->first(), - 'isFollowing' => auth()->check() && auth()->user()->isFollowing($user), - 'flight_api_url' => FlightProfileController::getUserFlightApiURL($user), - 'regions' => $regions, + 'isFollowing' => auth()->check() && auth()->user()->isFollowing($user), + 'flight_api_url' => FlightProfileController::getUserFlightApiURL($user), + 'regions' => $regions, + 'alliance' => $alliance, + 'airlines' => $airlines, + 'continents' => $continents, + 'aircraft_families' => $aircraftFamilies, ]); } diff --git a/app/Http/Controllers/Api/UserApiController.php b/app/Http/Controllers/Api/UserApiController.php index 28ecfda..16b381d 100644 --- a/app/Http/Controllers/Api/UserApiController.php +++ b/app/Http/Controllers/Api/UserApiController.php @@ -7,6 +7,7 @@ use App\Models\User; use App\Models\UserFlight; use Carbon\Carbon; use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; class UserApiController extends ApiController { @@ -47,7 +48,7 @@ class UserApiController extends ApiController ]); } - public function flights(string $username): JsonResponse + public function flights(string $username, Request $request): JsonResponse { $user = User::where('name', 'ilike', $username)->first(); @@ -55,6 +56,6 @@ class UserApiController extends ApiController return response()->json(['message' => 'User not found'], 404); } - return response()->json($user->FlightController()->flights()); + return response()->json($user->FlightController()->flights($request)); } } diff --git a/app/Http/Controllers/FlightProfileController.php b/app/Http/Controllers/FlightProfileController.php index 8bab328..8579adf 100644 --- a/app/Http/Controllers/FlightProfileController.php +++ b/app/Http/Controllers/FlightProfileController.php @@ -22,6 +22,7 @@ class FlightProfileController extends Controller 'selectedFlightId' => $selectedFlightId, 'flight_api_url' => self::getUserFlightApiURL($user), 'isFollowing' => auth()->check() && auth()->user()->isFollowing($user), + 'flightCount' => $user->departedFlights()->count(), ]; } diff --git a/app/Http/Controllers/UserFlightController.php b/app/Http/Controllers/UserFlightController.php index 78c9c53..70f96dc 100644 --- a/app/Http/Controllers/UserFlightController.php +++ b/app/Http/Controllers/UserFlightController.php @@ -15,7 +15,8 @@ class UserFlightController extends Controller $this->user = $user; } - public function flights(){ + public function flights(?Request $request = null) + { return UserFlight::where('user_id', $this->user->id) ->with([ 'departureAirport.region.country', @@ -30,6 +31,7 @@ class UserFlightController extends Controller 'flightClass', 'crewType' ]) + ->when($request?->boolean('departed_only'), fn($q) => $q->where('departure_date', '<=', now('UTC'))) ->orderBy('departure_date', 'desc') ->get(); } diff --git a/app/Models/Achievement.php b/app/Models/Achievement.php index ca13693..3233b1f 100644 --- a/app/Models/Achievement.php +++ b/app/Models/Achievement.php @@ -40,6 +40,7 @@ class Achievement extends Model 'achievement_difficulty_id', 'threshold', 'has_page', + 'sort_order', ]; protected $casts = [ diff --git a/app/Models/Aircraft.php b/app/Models/Aircraft.php index 4974837..a314892 100644 --- a/app/Models/Aircraft.php +++ b/app/Models/Aircraft.php @@ -26,9 +26,29 @@ class Aircraft extends Model 'display_name_short' ]; - const array IATA_ALIAS_MAP = [ - '7S8' => '73H', - '7S9' => '73J' + public const array BOEING_FAMILIES = [ + '707' => ['B701', 'B703', 'B720'], + '717' => ['B712', 'B717'], + '727' => ['B721', 'B722', 'B727'], + '737' => ['B731', 'B732', 'B733', 'B734', 'B735', 'B736', 'B737', 'B738', 'B739', 'B37M', 'B38M', 'B39M'], + '747' => ['B741', 'B742', 'B743', 'B744', 'B748', 'B74D', 'B74R', 'B74S'], + '757' => ['B752', 'B753', 'B757'], + '767' => ['B762', 'B763', 'B764', 'B767'], + '777' => ['B772', 'B773', 'B77L', 'B77W', 'B778', 'B779'], + '787' => ['B788', 'B789', 'B78X'], + ]; + + public const array AIRBUS_FAMILIES = [ + 'A300' => ['A30B', 'A300', 'A306'], + 'A310' => ['A310', 'A312', 'A313'], + 'A318' => ['A318'], + 'A319' => ['A319', 'A31X'], + 'A320' => ['A320', 'A20N'], + 'A321' => ['A321', 'A21N'], + 'A330' => ['A330', 'A332', 'A333', 'A338', 'A339'], + 'A340' => ['A340', 'A342', 'A343', 'A345', 'A346'], + 'A350' => ['A350', 'A358', 'A359', 'A35K'], + 'A380' => ['A380', 'A388'], ]; protected function displayName() : Attribute{ diff --git a/app/Models/User.php b/app/Models/User.php index f5691b2..a75ba02 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -55,6 +55,14 @@ class User extends Authenticatable return $this->hasMany(UserFlight::class); } + public function departedFlights() : HasMany { + return $this->flights()->where('departure_date', '<=', now('UTC')); + } + + public function upcomingFlights() : HasMany { + return $this->flights()->where('departure_date', '>=', now('UTC')); + } + public function ImportedFlights(): HasMany { return $this->hasMany(ImportedFlight::class); diff --git a/app/Services/Achievements/AchievementService.php b/app/Services/Achievements/AchievementService.php index f3f03c4..ceeb0a7 100644 --- a/app/Services/Achievements/AchievementService.php +++ b/app/Services/Achievements/AchievementService.php @@ -59,7 +59,7 @@ class AchievementService 'arrivalAirport.region', 'departureAirport.region.continent', 'arrivalAirport.region.continent', - ])->get(); + ])->where('departure_date', '<=', now('UTC'))->get(); foreach ($this->checkers as $checkerClass) { $checker = new $checkerClass($this); diff --git a/app/Services/Achievements/Checkers/AircraftChecker.php b/app/Services/Achievements/Checkers/AircraftChecker.php index 3ac243f..e0c7fa6 100644 --- a/app/Services/Achievements/Checkers/AircraftChecker.php +++ b/app/Services/Achievements/Checkers/AircraftChecker.php @@ -2,37 +2,13 @@ namespace App\Services\Achievements\Checkers; +use App\Models\Aircraft; use App\Models\User; use App\Models\UserFlight; use Illuminate\Support\Collection; class AircraftChecker extends BaseChecker { - private const array BOEING_FAMILIES = [ - '707' => ['B701', 'B703', 'B720'], - '717' => ['B712', 'B717'], - '727' => ['B721', 'B722', 'B727'], - '737' => ['B731', 'B732', 'B733', 'B734', 'B735', 'B736', 'B737', 'B738', 'B739', 'B37M', 'B38M', 'B39M'], - '747' => ['B741', 'B742', 'B743', 'B744', 'B748', 'B74D', 'B74R', 'B74S'], - '757' => ['B752', 'B753', 'B757'], - '767' => ['B762', 'B763', 'B764', 'B767'], - '777' => ['B772', 'B773', 'B77L', 'B77W', 'B778', 'B779'], - '787' => ['B788', 'B789', 'B78X'], - ]; - - private const array AIRBUS_FAMILIES = [ - 'A300' => ['A30B', 'A300', 'A306'], - 'A310' => ['A310', 'A312', 'A313'], - 'A318' => ['A318'], - 'A319' => ['A319', 'A31X'], - 'A320' => ['A320', 'A20N'], - 'A321' => ['A321', 'A21N'], - 'A330' => ['A330', 'A332', 'A333', 'A338', 'A339'], - 'A340' => ['A340', 'A342', 'A343', 'A345', 'A346'], - 'A350' => ['A350', 'A358', 'A359', 'A35K'], - 'A380' => ['A380', 'A388'], - ]; - private const array DOUBLE_DECKER_DESIGNATORS = [ // A380 'A380', 'A388', @@ -121,7 +97,7 @@ class AircraftChecker extends BaseChecker // --- Boeing 7x7 families --- - $flownBoeingFamilies = collect(self::BOEING_FAMILIES) + $flownBoeingFamilies = collect(Aircraft::BOEING_FAMILIES) ->filter(fn($designators) => $flightsWithAircraft->contains( fn(UserFlight $f) => in_array($f->aircraft->designator, $designators) @@ -133,7 +109,7 @@ class AircraftChecker extends BaseChecker // --- Airbus A3xx families --- - $flownAirbusFamilie = collect(self::AIRBUS_FAMILIES) + $flownAirbusFamilie = collect(Aircraft::AIRBUS_FAMILIES) ->filter(fn($designators) => $flightsWithAircraft->contains( fn(UserFlight $f) => in_array($f->aircraft->designator, $designators) diff --git a/app/Services/Achievements/Checkers/CountriesAndContinentsChecker.php b/app/Services/Achievements/Checkers/CountriesAndContinentsChecker.php index 812545a..a710ca1 100644 --- a/app/Services/Achievements/Checkers/CountriesAndContinentsChecker.php +++ b/app/Services/Achievements/Checkers/CountriesAndContinentsChecker.php @@ -76,6 +76,13 @@ class CountriesAndContinentsChecker extends BaseChecker $dep = $flight->departureAirport->region->continent->internal_name; $arr = $flight->arrivalAirport->region->continent->internal_name; + if (!in_array($dep, self::INHABITED_CONTINENTS) || !in_array($arr, self::INHABITED_CONTINENTS)) continue; + if ($dep === $arr) { + $depCountry = $flight->departureAirport->region->country_id; + $arrCountry = $flight->arrivalAirport->region->country_id; + if ($depCountry === $arrCountry) continue; + } + // Directed route key e.g. "europe→asia" $directedRoutes->push("{$dep}→{$arr}"); diff --git a/app/Services/Achievements/Checkers/GeneralFlyingChecker.php b/app/Services/Achievements/Checkers/GeneralFlyingChecker.php index 9db9479..8a2e140 100644 --- a/app/Services/Achievements/Checkers/GeneralFlyingChecker.php +++ b/app/Services/Achievements/Checkers/GeneralFlyingChecker.php @@ -70,6 +70,11 @@ class GeneralFlyingChecker extends BaseChecker // --- Progressive achievements --- + $totalDistance = $flights->sum('distance'); + + $this->awardProgress((int) $totalDistance, 'general_flying.circumference_of_the_earth'); + $this->awardProgress((int) $totalDistance, 'general_flying.to_the_moon'); + $this->awardProgress($count,'general_flying.10_flights'); $this->awardProgress($count,'general_flying.50_flights'); $this->awardProgress($count,'general_flying.100_flights'); diff --git a/database/migrations/2026_05_16_105657_add_distance_achievement.php b/database/migrations/2026_05_16_105657_add_distance_achievement.php new file mode 100644 index 0000000..4ba5cda --- /dev/null +++ b/database/migrations/2026_05_16_105657_add_distance_achievement.php @@ -0,0 +1,102 @@ + 'Circumnavigator', + 'internal_name' => 'general_flying.circumference_of_the_earth', + 'short_description' => 'Fly the same distance as the circumference of the Earth at the equator!', + 'icon' => 'standard_achievement.png', + 'progressive' => true, + 'long_description' => '', + 'achievement_category_id' => AchievementCategory::where('internal_name', 'general_flying')->first()->id, + 'achievement_difficulty_id' => AchievementDifficulty::where('internal_name', 'moderate')->first()->id, + 'threshold' => 40075, + 'has_page' => false, + ]); + + Achievement::create([ + 'name' => 'Fly Me to The Moon', + 'internal_name' => 'general_flying.to_the_moon', + 'short_description' => 'Fly the same distance as the Earth to the Moon!', + 'icon' => 'standard_achievement.png', + 'long_description' => '', + 'progressive' => true, + 'threshold' => 384400, + 'achievement_category_id' => AchievementCategory::where('internal_name', 'general_flying')->first()->id, + 'achievement_difficulty_id' => AchievementDifficulty::where('internal_name', 'hard')->first()->id, + 'has_page' => false, + ]); + + Achievement::whereInternalName('aircraft.all_boeing_7x7')->update(['has_page' => true]); + Achievement::whereInternalName('aircraft.all_airbus_a3xx')->update(['has_page' => true]); + Airline::whereInternalName('south-africa-airways')->update(['name' => 'South African Airways']); + + Schema::table('achievements', function (Blueprint $table) { + $table->unsignedInteger('sort_order')->nullable()->after('id'); + }); + + // Seed sort_order from current id order, scoped per category + $achievements = DB::table('achievements') + ->orderBy('achievement_category_id') + ->orderBy('id') + ->get(); + + $position = 1; + $currentCategory = null; + + foreach ($achievements as $achievement) { + if ($achievement->achievement_category_id !== $currentCategory) { + $position = 1; + $currentCategory = $achievement->achievement_category_id; + } + DB::table('achievements') + ->where('id', $achievement->id) + ->update(['sort_order' => $position++]); + } + + // Move "Four on the Floor" (id 30) after "Triple Threat" (id 34) + // within the aircraft category — swap their sort_order values + $triEngine = DB::table('achievements')->where('internal_name', 'aircraft.tri_engine')->first(); + $quadEngine = DB::table('achievements')->where('internal_name', 'aircraft.quad_engine')->first(); + + DB::table('achievements')->where('internal_name', 'aircraft.quad_engine') + ->update(['sort_order' => $triEngine->sort_order + 1]); + + // Shift everything between them up by 1 to make room + DB::table('achievements') + ->where('achievement_category_id', $quadEngine->achievement_category_id) + ->where('sort_order', '>=', $triEngine->sort_order + 1) + ->where('internal_name', '!=', 'aircraft.quad_engine') + ->increment('sort_order'); + + $users = User::all(); + + foreach ($users as $user) { + $user->calculateAchievements(); + } + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // + } +}; diff --git a/resources/css/app.css b/resources/css/app.css index 367f383..f7e46df 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -103,12 +103,16 @@ body { background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); color: #778; + position: relative; + overflow: hidden; } .class-premium-global { background: rgba(75, 32, 137, 0.35); border: 1px solid rgba(180, 130, 255, 0.25); color: #c49dff; + position: relative; + overflow: hidden; } .class-premium_economy-global { diff --git a/resources/js/Components/Distance.vue b/resources/js/Components/Distance.vue new file mode 100644 index 0000000..8801fb4 --- /dev/null +++ b/resources/js/Components/Distance.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/resources/js/Components/FlightsGoneBy/AchievementCard.vue b/resources/js/Components/FlightsGoneBy/AchievementCard.vue index 49971e5..c088df9 100644 --- a/resources/js/Components/FlightsGoneBy/AchievementCard.vue +++ b/resources/js/Components/FlightsGoneBy/AchievementCard.vue @@ -5,6 +5,13 @@ import {computed} from "vue"; import InlineBadge from "@/Components/FlightsGoneBy/InlineBadge.vue"; import GlassTooltip from "@/Components/FlightsGoneBy/GlassTooltip.vue"; import {Link} from '@inertiajs/vue3' +import ButtonLink from "@/Components/FlightsGoneBy/ButtonLink.vue"; +import Distance from "@/Components/Distance.vue"; + +const distanceAchievements = [ + 'general_flying.circumference_of_the_earth', + 'general_flying.to_the_moon', +]; const props = defineProps<{ achievement: Achievement @@ -85,13 +92,11 @@ const difficultyVariant = computed(() => {

{{ achievement.short_description }}

- - View Details - + - - + +
+ + @@ -115,19 +126,17 @@ const difficultyVariant = computed(() => { transition: opacity 0.2s ease, transform 0.2s ease; } -.achievement-card.locked { +.achievement-card.locked .achievement-inner { opacity: 0.45; } -.achievement-card:hover { - opacity: 1; - transform: translateY(-1px); -} +.achievement-card:hover .achievement-inner, .achievement-inner { display: flex; gap: 1rem; align-items: flex-start; + opacity: 1; } .achievement-icon-wrap { diff --git a/resources/js/Components/FlightsGoneBy/AirlineAlphabetTable.vue b/resources/js/Components/FlightsGoneBy/AirlineAlphabetTable.vue new file mode 100644 index 0000000..360cd9b --- /dev/null +++ b/resources/js/Components/FlightsGoneBy/AirlineAlphabetTable.vue @@ -0,0 +1,112 @@ + + + + + diff --git a/resources/js/Components/FlightsGoneBy/AllianceChallenge.vue b/resources/js/Components/FlightsGoneBy/AllianceChallenge.vue new file mode 100644 index 0000000..2aa982b --- /dev/null +++ b/resources/js/Components/FlightsGoneBy/AllianceChallenge.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/resources/js/Components/FlightsGoneBy/AlphabetTable.vue b/resources/js/Components/FlightsGoneBy/AlphabetTable.vue new file mode 100644 index 0000000..f1b025e --- /dev/null +++ b/resources/js/Components/FlightsGoneBy/AlphabetTable.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/resources/js/Components/FlightsGoneBy/BoardingPass.vue b/resources/js/Components/FlightsGoneBy/BoardingPass.vue index af3fa25..e18f386 100644 --- a/resources/js/Components/FlightsGoneBy/BoardingPass.vue +++ b/resources/js/Components/FlightsGoneBy/BoardingPass.vue @@ -3,6 +3,7 @@ import { Flight } from "@/Types/types"; import AirlineLogo from "@/Components/FlightsGoneBy/AirlineLogo.vue"; import AirportToolTip from "@/Components/FlightsGoneBy/AirportToolTip.vue"; import AircraftToolTip from "@/Components/FlightsGoneBy/AircraftToolTip.vue"; +import Distance from "@/Components/Distance.vue"; defineProps<{ flight: Flight @@ -70,7 +71,7 @@ defineProps<{ · DISTANCE - {{ Math.round(flight.distance).toLocaleString() }} km + @@ -80,16 +81,6 @@ defineProps<{ diff --git a/resources/js/Components/FlightsGoneBy/DepartureBoard.vue b/resources/js/Components/FlightsGoneBy/DepartureBoard.vue index b8b2149..4ddda8f 100644 --- a/resources/js/Components/FlightsGoneBy/DepartureBoard.vue +++ b/resources/js/Components/FlightsGoneBy/DepartureBoard.vue @@ -13,6 +13,7 @@ import GlassTooltip from "@/Components/FlightsGoneBy/GlassTooltip.vue"; import CrewTooltip from "@/Components/FlightsGoneBy/CrewTooltip.vue"; import {Link, router} from "@inertiajs/vue3"; import AllianceLogo from "@/Components/FlightsGoneBy/AllianceLogo.vue"; +import Distance from "@/Components/Distance.vue"; const props = defineProps<{ flightStats: FlightStats @@ -238,7 +239,7 @@ watch( - {{ (item as Flight).distance ? Math.round((item as Flight).distance).toLocaleString() + ' km' : '' }} + diff --git a/resources/js/Components/FlightsGoneBy/Feed/FlightBookedFeedItem.vue b/resources/js/Components/FlightsGoneBy/Feed/FlightBookedFeedItem.vue index 9eaa681..891942a 100644 --- a/resources/js/Components/FlightsGoneBy/Feed/FlightBookedFeedItem.vue +++ b/resources/js/Components/FlightsGoneBy/Feed/FlightBookedFeedItem.vue @@ -10,7 +10,7 @@ const props = defineProps<{ diff --git a/resources/js/Components/FlightsGoneBy/FlightBadge.vue b/resources/js/Components/FlightsGoneBy/FlightBadge.vue new file mode 100644 index 0000000..f909d36 --- /dev/null +++ b/resources/js/Components/FlightsGoneBy/FlightBadge.vue @@ -0,0 +1,30 @@ + + + + + diff --git a/resources/js/Components/FlightsGoneBy/FlightMap.vue b/resources/js/Components/FlightsGoneBy/FlightMap.vue index 4507223..da91656 100644 --- a/resources/js/Components/FlightsGoneBy/FlightMap.vue +++ b/resources/js/Components/FlightsGoneBy/FlightMap.vue @@ -471,6 +471,7 @@ export default defineComponent({ map = new maplibregl.Map({ container: mapContainer.value!, cooperativeGestures: true, + attributionControl: false, style: { version: 8, sources: { @@ -483,7 +484,6 @@ export default defineComponent({ 'https://d.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}@2x.png', ], tileSize: 256, - attribution: '© OpenStreetMap © CARTO', maxzoom: 19, }, }, diff --git a/resources/js/Components/FlightsGoneBy/FlightRegionTable.vue b/resources/js/Components/FlightsGoneBy/FlightRegionTable.vue index 1bb95c5..66cea27 100644 --- a/resources/js/Components/FlightsGoneBy/FlightRegionTable.vue +++ b/resources/js/Components/FlightsGoneBy/FlightRegionTable.vue @@ -1,49 +1,47 @@ diff --git a/resources/js/Components/FlightsGoneBy/FlightStatsBar.vue b/resources/js/Components/FlightsGoneBy/FlightStatsBar.vue index 27287b9..5ed200a 100644 --- a/resources/js/Components/FlightsGoneBy/FlightStatsBar.vue +++ b/resources/js/Components/FlightsGoneBy/FlightStatsBar.vue @@ -35,18 +35,13 @@
@@ -105,6 +100,7 @@ + + + + diff --git a/resources/js/Components/FlightsGoneBy/GlassTooltip.vue b/resources/js/Components/FlightsGoneBy/GlassTooltip.vue index e87b83b..14b03a4 100644 --- a/resources/js/Components/FlightsGoneBy/GlassTooltip.vue +++ b/resources/js/Components/FlightsGoneBy/GlassTooltip.vue @@ -29,8 +29,6 @@ defineProps<{ } .glass-tooltip { - background: var(--surface); - border: 1px solid var(--table-border); padding: 10px 14px; min-width: 180px; display: flex; @@ -38,5 +36,6 @@ defineProps<{ gap: 8px; color: var(--text); font-size: 0.85rem; + z-index: 20000 } diff --git a/resources/js/Components/FlightsGoneBy/InlineBadge.vue b/resources/js/Components/FlightsGoneBy/InlineBadge.vue index 2186b53..25d2102 100644 --- a/resources/js/Components/FlightsGoneBy/InlineBadge.vue +++ b/resources/js/Components/FlightsGoneBy/InlineBadge.vue @@ -17,7 +17,7 @@ withDefaults(defineProps<{ diff --git a/resources/js/Components/FlightsGoneBy/ProfileHeader.vue b/resources/js/Components/FlightsGoneBy/ProfileHeader.vue index 0c92f44..cb6dfd0 100644 --- a/resources/js/Components/FlightsGoneBy/ProfileHeader.vue +++ b/resources/js/Components/FlightsGoneBy/ProfileHeader.vue @@ -9,6 +9,7 @@ const props = defineProps<{ flightCount?: number achievementCount?: number isFollowing?: boolean + show: "flights" | "achievements" }>() const auth = usePage().props.auth @@ -20,6 +21,13 @@ const processing = ref(false) const snackbar = ref(false) const snackbarMessage = ref('') +const counts = computed(() => { + return { + flights: props.flightCount ?? 0, + achievements: props.achievementCount ?? 0, + } as Record<"flights" | "achievements", number> +}) + const follow = async () => { processing.value = true const response = await fetch(route('profile.follow', { user: props.user.name }), { @@ -61,8 +69,8 @@ const follow = async () => {
- {{ flightCount ?? achievementCount }} - {{achievementCount ? 'Achievements' : 'Flights'}} + {{ counts[show] }} + {{show.toUpperCase()}}
@@ -114,6 +122,12 @@ const follow = async () => { margin: 0; } +@media (max-width: 768px) { + .board-header { + padding: 1em + } +} + .follow-btn { font-family: 'Share Tech Mono', monospace; font-size: 0.75rem; diff --git a/resources/js/Components/FlightsGoneBy/ProfileLayout.vue b/resources/js/Components/FlightsGoneBy/ProfileLayout.vue index f6c3cd9..f4f1ad3 100644 --- a/resources/js/Components/FlightsGoneBy/ProfileLayout.vue +++ b/resources/js/Components/FlightsGoneBy/ProfileLayout.vue @@ -14,7 +14,7 @@ defineProps<{