Added splash page

This commit is contained in:
2026-06-21 18:52:25 +10:00
parent 07e2796e09
commit a39589ee6f
13 changed files with 1030 additions and 29 deletions
@@ -0,0 +1,32 @@
<?php
namespace App\Http\Controllers;
use App\Models\UserFlight;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Inertia\Inertia;
use Inertia\Response;
class HomePageController extends Controller
{
function mostRecentFlights()
{
return Cache::remember('splash_flights', now()->addHours(12), function () {
return UserFlight::query()
->with(['departureAirport', 'arrivalAirport'])
->whereHas('user', function ($query) {
$query->whereRaw("settings->>'profile_privacy' is distinct from 'private'");
})
->orderByDesc('departure_date')
->limit(50)
->get()
->values()
->toJson();
});
}
function splash(){
return Inertia::render('Splash');
}
}
@@ -32,12 +32,7 @@ class UserProfileController extends Controller
return redirect()->route($route, $args);
}
return redirect()->route('login');
}
public static function getUserFlightApiURL(User $user){
return config('app.logo_api_url').'/user/'.$user->name.'/flights';
//return '/data/user/'.$user->name.'/flights';
return redirect()->route('splash');
}
public function profileData(User $user, string $view, ?int $selectedFlightId = null) : array {
@@ -47,7 +42,6 @@ class UserProfileController extends Controller
'canEdit' => auth()->check() && (auth()->id() === $user->id || auth()->user()->hasRole('admin')),
'initialView' => $view,
'selectedFlightId' => $selectedFlightId,
'flight_api_url' => self::getUserFlightApiURL($user),
'followStatus' => auth()->check() ? auth()->user()->followStatus($user) : 'none',
'flightCount' => $user->departedFlights()->count(),
];
@@ -182,7 +176,6 @@ class UserProfileController extends Controller
'loggedInUser' => auth()->user(),
'userAchievement' => $canView ? $user->achievements()->where('achievement_id', $achievement->id)->first() : null,
'followStatus' => auth()->check() ? auth()->user()->followStatus($user) : 'none',
'flight_api_url' => UserProfileController::getUserFlightApiURL($user),
'regions' => $regions,
'alliance' => $alliance,
'airlines' => $airlines,
+1 -1
View File
@@ -15,7 +15,7 @@ class UserPolicy
}
$isPrivate = $profileUser->resolved_settings['private_profile'] == 'private';
$isPrivate = $profileUser->resolved_settings['profile_privacy'] == 'private';
if (!$isPrivate) {
return true;
+1 -1
View File
@@ -32,7 +32,7 @@ class SettingsRegistry
],
[
'category' => 'Account & Privacy',
'key' => 'private_profile',
'key' => 'profile_privacy',
'type' => 'select',
'label' => 'Account Privacy',
'default' => 'public',
+780 -5
View File
@@ -29,6 +29,7 @@
"cross-var": "^1.1.0",
"laravel-vite-plugin": "^3.0.0",
"postcss": "^8.4.31",
"sass-embedded": "^1.100.0",
"tailwindcss": "^3.2.1",
"typescript": "^6.0.2",
"vite": "^8.0.0",
@@ -95,6 +96,13 @@
"node": ">=6.9.0"
}
},
"node_modules/@bufbuild/protobuf": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.12.0.tgz",
"integrity": "sha512-B/XlCaFIP8LOwzo+bz5uFzATYokcwCKQcghqnlfwSmM5eX/qTkvDBnDPs+gXtX/RyjxJ4DRikECcPJbyALA8FA==",
"devOptional": true,
"license": "(Apache-2.0 AND BSD-3-Clause)"
},
"node_modules/@emnapi/core": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
@@ -416,6 +424,333 @@
"url": "https://github.com/sponsors/Boshen"
}
},
"node_modules/@parcel/watcher": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz",
"integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"dependencies": {
"detect-libc": "^2.0.3",
"is-glob": "^4.0.3",
"node-addon-api": "^7.0.0",
"picomatch": "^4.0.3"
},
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
},
"optionalDependencies": {
"@parcel/watcher-android-arm64": "2.5.6",
"@parcel/watcher-darwin-arm64": "2.5.6",
"@parcel/watcher-darwin-x64": "2.5.6",
"@parcel/watcher-freebsd-x64": "2.5.6",
"@parcel/watcher-linux-arm-glibc": "2.5.6",
"@parcel/watcher-linux-arm-musl": "2.5.6",
"@parcel/watcher-linux-arm64-glibc": "2.5.6",
"@parcel/watcher-linux-arm64-musl": "2.5.6",
"@parcel/watcher-linux-x64-glibc": "2.5.6",
"@parcel/watcher-linux-x64-musl": "2.5.6",
"@parcel/watcher-win32-arm64": "2.5.6",
"@parcel/watcher-win32-ia32": "2.5.6",
"@parcel/watcher-win32-x64": "2.5.6"
}
},
"node_modules/@parcel/watcher-android-arm64": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz",
"integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-darwin-arm64": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz",
"integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-darwin-x64": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz",
"integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-freebsd-x64": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz",
"integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-arm-glibc": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz",
"integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==",
"cpu": [
"arm"
],
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-arm-musl": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz",
"integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==",
"cpu": [
"arm"
],
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-arm64-glibc": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz",
"integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==",
"cpu": [
"arm64"
],
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-arm64-musl": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz",
"integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==",
"cpu": [
"arm64"
],
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-x64-glibc": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz",
"integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==",
"cpu": [
"x64"
],
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-linux-x64-musl": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz",
"integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==",
"cpu": [
"x64"
],
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-win32-arm64": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz",
"integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-win32-ia32": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz",
"integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==",
"cpu": [
"ia32"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher-win32-x64": {
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz",
"integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/parcel"
}
},
"node_modules/@parcel/watcher/node_modules/picomatch": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/@rolldown/binding-android-arm64": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.3.tgz",
@@ -2566,6 +2901,13 @@
"dev": true,
"license": "MIT"
},
"node_modules/colorjs.io": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz",
"integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==",
"devOptional": true,
"license": "MIT"
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -3167,7 +3509,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -3268,6 +3610,13 @@
"dev": true,
"license": "MIT"
},
"node_modules/immutable": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.6.tgz",
"integrity": "sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==",
"devOptional": true,
"license": "MIT"
},
"node_modules/invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
@@ -3311,7 +3660,7 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -3344,7 +3693,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
@@ -3965,6 +4314,13 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/node-addon-api": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
"license": "MIT",
"optional": true
},
"node_modules/node-releases": {
"version": "2.0.47",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz",
@@ -4567,12 +4923,401 @@
"version": "7.8.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
"integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
"dev": true,
"devOptional": true,
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/sass": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.100.0.tgz",
"integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==",
"license": "MIT",
"optional": true,
"dependencies": {
"chokidar": "^5.0.0",
"immutable": "^5.1.5",
"source-map-js": ">=0.6.2 <2.0.0"
},
"bin": {
"sass": "sass.js"
},
"engines": {
"node": ">=20.19.0"
},
"optionalDependencies": {
"@parcel/watcher": "^2.4.1"
}
},
"node_modules/sass-embedded": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.100.0.tgz",
"integrity": "sha512-Ut8wlQSk19tm7jMK6mz6cF1+e+E7tUnW2tM02zQDPnOTcVbV8qCQG8UWxZkkNlY50+hV3hqP24OOkUlMz8xBpw==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"@bufbuild/protobuf": "^2.5.0",
"colorjs.io": "^0.5.0",
"immutable": "^5.1.5",
"rxjs": "^7.4.0",
"supports-color": "^8.1.1",
"sync-child-process": "^1.0.2",
"varint": "^6.0.0"
},
"bin": {
"sass": "dist/bin/sass.js"
},
"engines": {
"node": ">=16.0.0"
},
"optionalDependencies": {
"sass-embedded-all-unknown": "1.100.0",
"sass-embedded-android-arm": "1.100.0",
"sass-embedded-android-arm64": "1.100.0",
"sass-embedded-android-riscv64": "1.100.0",
"sass-embedded-android-x64": "1.100.0",
"sass-embedded-darwin-arm64": "1.100.0",
"sass-embedded-darwin-x64": "1.100.0",
"sass-embedded-linux-arm": "1.100.0",
"sass-embedded-linux-arm64": "1.100.0",
"sass-embedded-linux-musl-arm": "1.100.0",
"sass-embedded-linux-musl-arm64": "1.100.0",
"sass-embedded-linux-musl-riscv64": "1.100.0",
"sass-embedded-linux-musl-x64": "1.100.0",
"sass-embedded-linux-riscv64": "1.100.0",
"sass-embedded-linux-x64": "1.100.0",
"sass-embedded-unknown-all": "1.100.0",
"sass-embedded-win32-arm64": "1.100.0",
"sass-embedded-win32-x64": "1.100.0"
}
},
"node_modules/sass-embedded-all-unknown": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.100.0.tgz",
"integrity": "sha512-auFtXY/kwYILmSVjtBDwyj0axcLbYYiffOKWoaXHnI5bsYwiRbBh3EneR1rpbX2ZIZCrwX93i5pxKLTZF/662Q==",
"cpu": [
"!arm",
"!arm64",
"!riscv64",
"!x64"
],
"license": "MIT",
"optional": true,
"dependencies": {
"sass": "1.100.0"
}
},
"node_modules/sass-embedded-android-arm": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.100.0.tgz",
"integrity": "sha512-70f3HgX2pFNmzpGQ86n5e6QfWn2fP4QUQGfFQK0P1XH73ZLIzLo2YqygrGKGKeeqtc5eU2Wl1/xQzhzuKnO4kw==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-android-arm64": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.100.0.tgz",
"integrity": "sha512-W+Ru9JwTnfU0UX3jSZcbqFdtKFMcYdfFwytc57h2DgnqCOIiAqI2E06mABZBZC+r3LwXCBuS5GbXAGeVgvVDkA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-android-riscv64": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.100.0.tgz",
"integrity": "sha512-icU3o0V/uCSytSpf+tX5Lf51BvyQEbLzDUJfUi9etSauYBGHpPKkdtdZH0si4v98phq11Kl8rSV1SggksxF1Hg==",
"cpu": [
"riscv64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-android-x64": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.100.0.tgz",
"integrity": "sha512-mevF9VQk6gEYByy8+jusaHGmd7Usb2ytX/DsEOd0JtOGCtcf1kh575xJ6OUBDIcJ15uLnbau/0iy1eP6WVBvWA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-darwin-arm64": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.100.0.tgz",
"integrity": "sha512-1PVlYi61POo93IT/FfrG1mc1tAHxeSTyUALF2aOFmXGWjVXr3bQzEQiBGCOvQbj/ix+5hNyXFXcEMEyKvtUJJA==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-darwin-x64": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.100.0.tgz",
"integrity": "sha512-x97o3JnGyImZNCIVs9wQHJUE5QCvmVIKaH1cwrz/5dK7OT1FpeNiW+u9TUomP9hG6Ekjd8EL8NBHpxTfIhdjmg==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-linux-arm": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.100.0.tgz",
"integrity": "sha512-9Ul7O1eKrc5YlhwWjkp8tZPSe3UEwSZ1uwUZOQom1HL0pRlBA6F/IlGZYFTLwnHMIP1fc77MMNaBRfc05mKMpw==",
"cpu": [
"arm"
],
"libc": "glibc",
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-linux-arm64": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.100.0.tgz",
"integrity": "sha512-Dwjmj8Z6VRy7rAi53JAdEwIyUjpfl7PhpSc2/LpQPQx+aO5Dp7Spaipkax0ufJl1SoDUdchCsM4y/88YaluorQ==",
"cpu": [
"arm64"
],
"libc": "glibc",
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-linux-musl-arm": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.100.0.tgz",
"integrity": "sha512-sl0JgbGloPyJg66XXx5UDSDScZ0oU85DpMQU4JU/sCUCFj1Z8zZ69SJWKTCNE4/jwnce7WI2zPCV5AG+RHOZJw==",
"cpu": [
"arm"
],
"libc": "musl",
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-linux-musl-arm64": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.100.0.tgz",
"integrity": "sha512-XpACJB2KjSLjf2e9uuvGVdOURsoNrFqgRiihhXyUHK9W0t3LIHb7z5MA/7XGPIT9bWSOO2zyw+rH/FHtDV/Yrg==",
"cpu": [
"arm64"
],
"libc": "musl",
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-linux-musl-riscv64": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.100.0.tgz",
"integrity": "sha512-ShvI0Kx04mwoCARwZ0UjiT97isQvzO80tAt91zmFyHLN9kelc/IrQi940farSm2xQVPCKdeVyeG0ekBsokSpYQ==",
"cpu": [
"riscv64"
],
"libc": "musl",
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-linux-musl-x64": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.100.0.tgz",
"integrity": "sha512-TDBCRWNuS4RDLQXvRc1gjZlWiWTWaWGp0Bwu/IKwJxov81lsvrCs3TihTyNXtW7V5aoN4Ky3r0QOkNb3mwmBnA==",
"cpu": [
"x64"
],
"libc": "musl",
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-linux-riscv64": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.100.0.tgz",
"integrity": "sha512-j4ENJGOheO+fm3j/yorLxCjBP6/XskrZx7dTLlT+lXYwN/qqCqoA/gsNLI0McS3DFM6GBwPiffzWsdWS8t6sEQ==",
"cpu": [
"riscv64"
],
"libc": "glibc",
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-linux-x64": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.100.0.tgz",
"integrity": "sha512-0vUSN8j0WGtCJIOPh//EmUvYGHW0QOe5iul8qyhPk50MAcw49MA0r34AhftjDdx94ILPF6vApFs0gwHPQRlpVA==",
"cpu": [
"x64"
],
"libc": "glibc",
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-unknown-all": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.100.0.tgz",
"integrity": "sha512-c+naBgWId4MIpToXcI0DgqetjdAkwTTAxFAuOaBz7HUXLdyG1oZRrEvSsbe41nEdQOKH0vgofVFCeSQgoXOG9A==",
"license": "MIT",
"optional": true,
"os": [
"!android",
"!darwin",
"!linux",
"!win32"
],
"dependencies": {
"sass": "1.100.0"
}
},
"node_modules/sass-embedded-win32-arm64": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.100.0.tgz",
"integrity": "sha512-iE+yxj+hUXwwbqpHkXxgAWTzeRfcWxJ7SSTQEPMk48lwq3oCrWLlz5sQuWHbuTK/i0GKQfROdP+hOmPi89yjUg==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-embedded-win32-x64": {
"version": "1.100.0",
"resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.100.0.tgz",
"integrity": "sha512-qI4F8MI7/KYoy9NdjJfhSspG42WPkADSNDvwEV7qWvCSFC83koJssRsKO2/PfY+niZz6BG65Ic/D+A11h959hw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass/node_modules/chokidar": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz",
"integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
"license": "MIT",
"optional": true,
"dependencies": {
"readdirp": "^5.0.0"
},
"engines": {
"node": ">= 20.19.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/sass/node_modules/readdirp": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz",
"integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
"license": "MIT",
"optional": true,
"engines": {
"node": ">= 20.19.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
@@ -4779,7 +5524,7 @@
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
"devOptional": true,
"license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
@@ -4804,6 +5549,29 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/sync-child-process": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz",
"integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"sync-message-port": "^1.0.0"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/sync-message-port": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.2.0.tgz",
"integrity": "sha512-gAQ9qrUN/UCypHtGFbbe7Rc/f9bzO88IwrG8TDo/aMKAApKyD6E3W4Cm0EfhfBb6Z6SKt59tTCTfD+n1xmAvMg==",
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/tailwindcss": {
"version": "3.4.19",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
@@ -5069,6 +5837,13 @@
"dev": true,
"license": "MIT"
},
"node_modules/varint": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz",
"integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==",
"devOptional": true,
"license": "MIT"
},
"node_modules/vite": {
"version": "8.0.16",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.16.tgz",
+1
View File
@@ -21,6 +21,7 @@
"cross-var": "^1.1.0",
"laravel-vite-plugin": "^3.0.0",
"postcss": "^8.4.31",
"sass-embedded": "^1.100.0",
"tailwindcss": "^3.2.1",
"typescript": "^6.0.2",
"vite": "^8.0.0",
+7 -1
View File
@@ -1,6 +1,8 @@
import { ref, onMounted, onUnmounted, type Ref } from 'vue'
import axios from 'axios'
import { api } from '@/api'
import { SharedProps } from "@/Types/types"
import { usePage } from "@inertiajs/vue3"
interface UseApiResourceReturn<T> {
data: Ref<T | null>
@@ -9,7 +11,9 @@ interface UseApiResourceReturn<T> {
refresh: () => Promise<void>
}
export function useApiResource<T>(url: string, immediate = true): UseApiResourceReturn<T> {
export function useApiResource<T>(route: string, immediate = true): UseApiResourceReturn<T> {
const page = usePage<SharedProps>() // resolved when the composable runs, inside setup()
const data = ref<T | null>(null) as Ref<T | null>
const loading = ref(true)
const error = ref<string | null>(null)
@@ -22,6 +26,8 @@ export function useApiResource<T>(url: string, immediate = true): UseApiResource
loading.value = true
error.value = null
// build the url here too, so it always reflects current page props
const url = `${page.props.logo_api_url}${route}`
try {
const response = await api.get<T>(url, { signal: controller.signal })
data.value = response.data
+2 -3
View File
@@ -2,9 +2,8 @@ import { computed } from 'vue'
import { useApiResource } from '@/Composables/useApiResource'
import type { Flight } from '@/Types/types'
export function useFlights(url: string, departedOnly: boolean = false) {
const requestUrl = departedOnly ? `${url}/departed` : url
const { data, loading, error } = useApiResource<Flight[]>(requestUrl)
export function useFlights(url: string) {
const { data, loading, error } = useApiResource<Flight[]>(url)
const flights = computed(() => data.value ?? [])
@@ -1,5 +1,5 @@
<script setup lang="ts">
import {Achievement, Airline, Continent, Region, User, UserAchievement} from "@/Types/types";
import {Achievement, Airline, Alliance, Continent, Region, User, UserAchievement} from "@/Types/types";
import ProfileLayout from "@/Components/FlightsGoneBy/ProfileLayout.vue";
import Panel from "@/Components/FlightsGoneBy/Panels/Panel.vue";
import {computed, defineAsyncComponent} from 'vue';
@@ -21,9 +21,8 @@ const props = defineProps<{
user: User
loggedInUser: User | null
followStatus: string
flight_api_url: string
regions: Region[]
alliance: string | null
alliance: Alliance | null
airlines: Airline[]
continents: Continent[]
aircraft_families: Record<string, string[]>
@@ -32,7 +31,7 @@ const props = defineProps<{
}>()
const { flights, flightsLoading } = useFlights(props.flight_api_url, true)
const { flights, flightsLoading } = useFlights(`/internal/user/${props.user.name}/flights/departed`)
const AchievementDetail = defineAsyncComponent(
() => import(`./Achievements/${props.achievement.internal_name}.vue`)
+193
View File
@@ -0,0 +1,193 @@
<script setup lang="ts">
import MainLayout from "@/Layouts/MainLayout.vue";
import GlassBox from "@/Components/FlightsGoneBy/GlassBox.vue";
import FlightMap from "@/Components/FlightsGoneBy/FlightMap.vue";
import {Head, Link, usePage} from "@inertiajs/vue3";
import {useFlights} from "@/Composables/useFlights";
import PlaneLoader from "@/Components/FlightsGoneBy/PlaneLoader.vue";
import {SharedProps} from "@/Types/types";
defineOptions({ layout: MainLayout });
const page = usePage<SharedProps>().props
const { flights, flightsLoading } = useFlights(`/internal/flights/most-recent`)
const features = [
{
icon: "✈️",
title: "Log every flight",
body: "Add flights manually in seconds, or import your history straight from MyFlightRadar24.",
},
{
icon: "🏆",
title: "Earn achievements",
body: "Unlock badges as you rack up airports, airlines, and miles.",
},
{
icon: "🗺️",
title: "Visualise your travels",
body: "See every route you've ever flown on one beautiful interactive map, a full departure board and all the graphs you could want.",
},
{
icon: "👥",
title: "Share with friends",
body: "Compare stats, routes, and bragging rights with people you know.",
},
];
</script>
<template>
<div class="splash-page">
<Head title="Welcome" />
<!-- HERO -->
<section class="hero">
<GlassBox
class="welcomeBox"
title="Welcome to FlightsGoneBy - The Ultimate Flight Diary"
blurb="Log the flights you've taken, share them with friends, earn achievements, and get beautiful visualisations and full control of your data."
/>
<div class="hero-actions" v-if="!page.auth.user">
<Link :href="route('register')" class="btn btn-primary">Get started it's free</Link>
<Link :href="route('login')" class="btn btn-secondary">Log in</Link>
</div>
</section>
<!-- MAP AS BACKDROP -->
<section class="map-section">
<div class="map-caption">
<span class="caption-icon">🛫</span>
Flights Recently Logged By Our Community
</div>
<FlightMap v-if="!flightsLoading" :flights="flights" :showLegend="false" />
<div v-if="flightsLoading" class="loading-state">
<PlaneLoader />
</div>
</section>
<!-- FEATURES -->
<section class="features-grid">
<GlassBox
v-for="feature in features"
:key="feature.title"
class="feature-card"
>
<span class="feature-icon">{{ feature.icon }}</span>
<h3>{{ feature.title }}</h3>
<p>{{ feature.body }}</p>
</GlassBox>
</section>
<!-- CLOSING CTA -->
<section class="cta-section" v-if="!page.auth.user">
<GlassBox class="cta-box">
<h2>Come join us today</h2>
<p>We'd love to have you be a part of our community.</p>
<Link :href="route('register')" class="btn btn-primary">Create your account</Link>
</GlassBox>
</section>
</div>
</template>
<style lang="sass" scoped>
.splash-page
width: 80%
max-width: 1100px
margin: 0 auto
display: flex
flex-direction: column
gap: 4rem
padding-block: 2rem
.hero
display: flex
flex-direction: column
align-items: center
gap: 1.5rem
text-align: center
.welcomeBox
width: 100%
.hero-actions
display: flex
gap: 1rem
.loading-state
display: flex
justify-content: center
align-items: center
min-height: 50dvh
.btn
padding: 0.75rem 1.75rem
font-weight: 600
text-decoration: none
transition: transform 0.15s ease
&:hover
transform: translateY(-2px)
.btn-primary
background: var(--accent, #3b82f6)
color: #fff
.btn-secondary
background: rgba(255, 255, 255, 0.1)
color: inherit
border: 1px solid rgba(255, 255, 255, 0.2)
.features-grid
display: grid
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr))
gap: 1em
.feature-card
text-align: center
display: flex
flex-direction: column
align-items: center
gap: 0.5rem
margin: 0
width: 100%
box-sizing: border-box
.feature-icon
font-size: 2rem
.cta-section
display: flex
justify-content: center
gap: 1em
.cta-box
text-align: center
display: flex
flex-direction: column
align-items: center
gap: 1rem
width: 100%
margin: 0
.map-section
position: relative
overflow: hidden
.map-caption
position: absolute
top: 1rem
left: 1rem
z-index: 10
display: inline-flex
align-items: center
gap: 0.5rem
padding: 0.5rem 1rem
background: rgba(10, 15, 30, 0.65)
backdrop-filter: blur(8px)
border: 1px solid rgba(255, 255, 255, 0.12)
border-radius: 999px
font-size: 0.85rem
font-weight: 500
color: rgba(255, 255, 255, 0.9)
</style>
+1 -2
View File
@@ -21,13 +21,12 @@ const props = defineProps<{
selectedFlightId?: number | null
initialView?: ProfileView
followStatus: string
flight_api_url: string
flightCount: number
}>()
// ── Flights state ─────────────────────────────────────────────────────────────
const { flights, flightsLoading } = useFlights(props.flight_api_url)
const { flights, flightsLoading } = useFlights(`/internal/user/${props.user.name}/flights`)
const localSelectedFlightId = ref(props.selectedFlightId ?? null)
// ── Filter state ──────────────────────────────────────────────────────────────
+5 -4
View File
@@ -3,6 +3,7 @@
use App\Http\Controllers\Api\AircraftApiController;
use App\Http\Controllers\Api\AirlineApiController;
use App\Http\Controllers\Api\UserApiController;
use App\Http\Controllers\HomePageController;
use Illuminate\Support\Facades\Route;
Route::domain(config('app.api_domain'))->group(function () {
@@ -12,10 +13,10 @@ Route::domain(config('app.api_domain'))->group(function () {
return response()->json(['message' => 'Welcome to the FlightsGoneBy API']);
});
Route::prefix('user')->controller(UserApiController::class)->middleware('sanctum.or.trusted')->group(function () {
Route::get('{user}/flights', 'viewableFlights')->name('api.user.flights');
Route::get('{user}/flights/departed', 'viewableDepartedFlights')->name('api.user.flights.departed');
Route::get('{user}/flights/upcoming', 'viewableUpcomingFlights')->name('api.user.flights.departed');
Route::prefix('internal')->middleware('sanctum.or.trusted')->group(function () {
Route::get('/user/{user}/flights', [UserApiController::class, 'viewableFlights'])->name('api.user.flights');
Route::get('/user/{user}/flights/departed', [UserApiController::class, 'viewableDepartedFlights'])->name('api.user.flights.departed');
Route::get('/flights/most-recent', [HomePageController::class ,'mostRecentFlights'])->name('api.user.flights.departed');
});
+3
View File
@@ -10,6 +10,7 @@ use App\Http\Controllers\FeedController;
use App\Http\Controllers\FlightController;
use App\Http\Controllers\FlightImportController;
use App\Http\Controllers\FollowerController;
use App\Http\Controllers\HomePageController;
use App\Http\Controllers\UserProfileController;
use App\Http\Controllers\LogoController;
use App\Http\Controllers\NotificationController;
@@ -33,6 +34,8 @@ Route::domain(config('app.domain'))->group(
function() {
Route::get('/', [UserProfileController::class, 'index'])->name('home');
Route::get('/splash', [HomePageController::class, 'splash'])->name('splash');
Route::get('/dashboard', function () {
return Inertia::render('Dashboard');