Added Notifications

This commit is contained in:
2026-05-24 21:53:17 +10:00
parent 150c34bfb8
commit 57b015eb18
8 changed files with 57 additions and 11 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ use App\Traits\HasAchievements;
use App\Models\Notification; use App\Models\Notification;
use Laravel\Sanctum\HasApiTokens; use Laravel\Sanctum\HasApiTokens;
#[Fillable(['name', 'email', 'password'])] #[Fillable(['name', 'email', 'password', 'distance_unit'])]
#[Hidden(['password', 'remember_token'])] #[Hidden(['password', 'remember_token'])]
class User extends Authenticatable class User extends Authenticatable
{ {
@@ -0,0 +1,26 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('distance_unit', 3)->default('km')->after('id');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
//
}
};
@@ -7,6 +7,7 @@ import GlassTooltip from "@/Components/FlightsGoneBy/GlassTooltip.vue";
import {Link} from '@inertiajs/vue3' import {Link} from '@inertiajs/vue3'
import ButtonLink from "@/Components/FlightsGoneBy/ButtonLink.vue"; import ButtonLink from "@/Components/FlightsGoneBy/ButtonLink.vue";
import Distance from "@/Components/Distance.vue"; import Distance from "@/Components/Distance.vue";
import FormattedNumber from "@/Components/FormattedNumber.vue";
const distanceAchievements = [ const distanceAchievements = [
'general_flying.circumference_of_the_earth', 'general_flying.circumference_of_the_earth',
@@ -18,6 +19,7 @@ const props = defineProps<{
achievement: Achievement achievement: Achievement
userAchievement?: UserAchievement userAchievement?: UserAchievement
user?: User user?: User
distanceUnit? : "mi" | "km" | "nm"
}>() }>()
const progress = computed(() => { const progress = computed(() => {
@@ -101,7 +103,14 @@ const difficultyVariant = computed(() => {
<template v-if="achievement.progressive && progress"> <template v-if="achievement.progressive && progress">
<div class="progress-label"> <div class="progress-label">
<span><distance :showUnits="false" :value="Math.min(progress.current, progress.threshold)" /> / <distance :value="progress.threshold" :showUnits="distanceAchievements.includes(achievement.internal_name)" /></span> <span v-if="distanceAchievements.includes(achievement.internal_name)">
<Distance :unit="distanceUnit" :showUnits="false" :value="Math.min(progress.current, progress.threshold)" /> /
<Distance :unit="distanceUnit" :value="progress.threshold" />
</span>
<span v-else>
<FormattedNumber :value="Math.min(progress.current, progress.threshold)" /> /
<FormattedNumber :value="progress.threshold" />
</span>
<span>{{ progress.percentage }}%</span> <span>{{ progress.percentage }}%</span>
</div> </div>
<v-progress-linear <v-progress-linear
@@ -1,10 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import {Flight, User} from "@/Types/types"; import {Flight, SharedProps, User} from "@/Types/types";
import AirlineLogo from "@/Components/FlightsGoneBy/AirlineLogo.vue"; import AirlineLogo from "@/Components/FlightsGoneBy/AirlineLogo.vue";
import AirportToolTip from "@/Components/FlightsGoneBy/AirportToolTip.vue"; import AirportToolTip from "@/Components/FlightsGoneBy/AirportToolTip.vue";
import AircraftToolTip from "@/Components/FlightsGoneBy/AircraftToolTip.vue"; import AircraftToolTip from "@/Components/FlightsGoneBy/AircraftToolTip.vue";
import Distance from "@/Components/Distance.vue"; import Distance from "@/Components/Distance.vue";
import UserFlightContextMenu from "@/Components/FlightsGoneBy/UserFlightContextMenu.vue"; import UserFlightContextMenu from "@/Components/FlightsGoneBy/UserFlightContextMenu.vue";
import {usePage} from "@inertiajs/vue3";
defineProps<{ defineProps<{
flight: Flight flight: Flight
@@ -13,6 +14,7 @@ defineProps<{
user?: User user?: User
}>() }>()
const page = usePage<SharedProps>().props
</script> </script>
@@ -75,7 +77,7 @@ defineProps<{
<span class="pass-stat-divider" v-if="flight.duration_display && flight.distance">·</span> <span class="pass-stat-divider" v-if="flight.duration_display && flight.distance">·</span>
<span v-if="flight.distance" class="pass-stat"> <span v-if="flight.distance" class="pass-stat">
<span class="pass-stat-label">DISTANCE</span> <span class="pass-stat-label">DISTANCE</span>
<span class="pass-stat-value"><Distance :value="Math.round(flight.distance)" /></span> <span class="pass-stat-value"><Distance :unit="page.auth?.user?.distance_unit" :value="Math.round(flight.distance)" /></span>
</span> </span>
</div> </div>
</div> </div>
@@ -2,7 +2,7 @@
import FlightClassBadge from "@/Components/FlightsGoneBy/FlightClassBadge.vue"; import FlightClassBadge from "@/Components/FlightsGoneBy/FlightClassBadge.vue";
import AirlineLogo from "@/Components/FlightsGoneBy/AirlineLogo.vue"; import AirlineLogo from "@/Components/FlightsGoneBy/AirlineLogo.vue";
import {Flight, User} from "@/Types/types"; import {Flight, SharedProps, User} from "@/Types/types";
import { computed, ref, watch, nextTick } from "vue"; import { computed, ref, watch, nextTick } from "vue";
import type { DataTableSortItem } from 'vuetify'; import type { DataTableSortItem } from 'vuetify';
import InlineBadge from "@/Components/FlightsGoneBy/InlineBadge.vue"; import InlineBadge from "@/Components/FlightsGoneBy/InlineBadge.vue";
@@ -12,6 +12,7 @@ import {FlightStats} from "@/Composables/useFlightStats";
import CrewTooltip from "@/Components/FlightsGoneBy/CrewTooltip.vue"; import CrewTooltip from "@/Components/FlightsGoneBy/CrewTooltip.vue";
import Distance from "@/Components/Distance.vue"; import Distance from "@/Components/Distance.vue";
import UserFlightContextMenu from "@/Components/FlightsGoneBy/UserFlightContextMenu.vue"; import UserFlightContextMenu from "@/Components/FlightsGoneBy/UserFlightContextMenu.vue";
import {usePage} from "@inertiajs/vue3";
const props = defineProps<{ const props = defineProps<{
flightStats: FlightStats flightStats: FlightStats
@@ -64,6 +65,7 @@ const customKeySort = {
}, },
} }
const page = usePage<SharedProps>()
const sortBy = ref<DataTableSortItem[]>([]) const sortBy = ref<DataTableSortItem[]>([])
const currentPage = ref(1) const currentPage = ref(1)
@@ -226,7 +228,7 @@ watch(
<td class="v-data-table__td"> <td class="v-data-table__td">
<span class="mono-tag distance-cell"> <span class="mono-tag distance-cell">
<Distance :value="Math.round((item as Flight).distance)" /> <Distance :unit="page.props.auth.user?.distance_unit" :value="Math.round((item as Flight).distance)" />
</span> </span>
</td> </td>
@@ -35,12 +35,12 @@
<div class="stat"> <div class="stat">
<template v-if="totalDistanceKm"> <template v-if="totalDistanceKm">
<div class="stat-primary"> <div class="stat-primary">
<span class="stat-num"><Distance includeSpace :value="totalDistanceKm" /></span> <span class="stat-num"><Distance :unit="page.auth?.user?.distance_unit" includeSpace :value="totalDistanceKm" /></span>
</div> </div>
</template> </template>
<template v-if="upcomingDistanceKm"> <template v-if="upcomingDistanceKm">
<div :class="totalDistanceKm ? 'stat-upcoming' : 'stat-primary'"> <div :class="totalDistanceKm ? 'stat-upcoming' : 'stat-primary'">
<span :class="totalDistanceKm ? 'stat-upcoming-num' : 'stat-num'"><Distance includeSpace :value="upcomingDistanceKm"/></span> <span :class="totalDistanceKm ? 'stat-upcoming-num' : 'stat-num'"><Distance :unit="page.auth?.user?.distance_unit" includeSpace :value="upcomingDistanceKm"/></span>
</div> </div>
</template> </template>
</div> </div>
@@ -99,14 +99,17 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import type { Flight } from '@/Types/types' import type {Flight, SharedProps} from '@/Types/types'
import Distance from "@/Components/Distance.vue"; import Distance from "@/Components/Distance.vue";
import {usePage} from "@inertiajs/vue3";
const props = defineProps<{ const props = defineProps<{
flights: Flight[] flights: Flight[]
upcomingFlights: Flight[] upcomingFlights: Flight[]
}>() }>()
const page = usePage<SharedProps>().props
// ── Past ────────────────────────────────────────────────────────────────────── // ── Past ──────────────────────────────────────────────────────────────────────
const totalDistanceKm = computed(() => const totalDistanceKm = computed(() =>
+5 -2
View File
@@ -3,8 +3,8 @@ import { ref, computed } from "vue"
import ProfileLayout from "@/Components/FlightsGoneBy/ProfileLayout.vue" import ProfileLayout from "@/Components/FlightsGoneBy/ProfileLayout.vue"
import ProfileViewSwitcher from "@/Components/FlightsGoneBy/ProfileViewSwitcher.vue" import ProfileViewSwitcher from "@/Components/FlightsGoneBy/ProfileViewSwitcher.vue"
import AchievementCard from "@/Components/FlightsGoneBy/AchievementCard.vue" import AchievementCard from "@/Components/FlightsGoneBy/AchievementCard.vue"
import {Achievement, User, UserAchievement} from "@/Types/types" import {Achievement, SharedProps, User, UserAchievement} from "@/Types/types"
import { Head } from "@inertiajs/vue3"; import {Head, usePage} from "@inertiajs/vue3";
import MainLayout from "@/Layouts/MainLayout.vue"; import MainLayout from "@/Layouts/MainLayout.vue";
import Panel from "@/Components/FlightsGoneBy/Panels/Panel.vue"; import Panel from "@/Components/FlightsGoneBy/Panels/Panel.vue";
import PanelHeader from "@/Components/FlightsGoneBy/Panels/PanelHeader.vue"; import PanelHeader from "@/Components/FlightsGoneBy/Panels/PanelHeader.vue";
@@ -22,6 +22,8 @@ const props = defineProps<{
unlockedByCategory: Record<string, number> unlockedByCategory: Record<string, number>
}>() }>()
const page = usePage<SharedProps>().props
const hideImpossible = ref(false) const hideImpossible = ref(false)
const filteredAchievements = computed(() => { const filteredAchievements = computed(() => {
@@ -105,6 +107,7 @@ const filteredUnlockedCount = computed(() =>
:key="achievement.id" :key="achievement.id"
:achievement="achievement" :achievement="achievement"
:user-achievement="userAchievements[achievement.id]" :user-achievement="userAchievements[achievement.id]"
:distance-unit="page.auth?.user?.distance_unit"
/> />
</div> </div>
</Panel> </Panel>
+1
View File
@@ -17,6 +17,7 @@ export interface User {
name: string name: string
email: string email: string
email_verified_at: string | null email_verified_at: string | null
distance_unit: "km" | "mi" | "nm"
} }
export type UserActionType = "flight_cancelled" | "flight_booked" | "flight_updated" | "flight_logged" | "flight_deleted" | "flight_imported" | "flight_departing" | "flight_arriving" export type UserActionType = "flight_cancelled" | "flight_booked" | "flight_updated" | "flight_logged" | "flight_deleted" | "flight_imported" | "flight_departing" | "flight_arriving"