Added Notifications

This commit is contained in:
2026-05-16 23:48:18 +10:00
parent 69d72e0912
commit 1d5b9f340f
61 changed files with 4204 additions and 182 deletions
@@ -0,0 +1,115 @@
<script setup lang="ts">
import {Airport, Flight} from '@/Types/types'
import BadgeTable from '@/Components/FlightsGoneBy/GenericBadgeTable.vue'
import InlineBadge from '@/Components/FlightsGoneBy/InlineBadge.vue'
import AirportToolTip from '@/Components/FlightsGoneBy/AirportToolTip.vue'
type CodeType = 'iata' | 'icao'
const props = defineProps<{
letters: string[]
flightsByLetter: Record<string, Flight[]>
codeType: CodeType
selectedYear: number | null
}>()
function getCode(airport: Airport): string | null {
const raw = props.codeType === 'iata' ? airport.iata_code : airport.icao_code
return raw?.trim().toUpperCase() ?? null
}
interface AirportEntry {
airport: Airport
firstYear: number
}
function airportEntriesForLetter(letter: string): AirportEntry[] {
const flights = props.flightsByLetter[letter] ?? []
const seen = new Map<string, AirportEntry>()
for (const flight of flights) {
const year = new Date(flight.departure_date).getFullYear()
for (const airport of [flight.departure_airport, flight.arrival_airport]) {
const code = getCode(airport)
if (!code?.startsWith(letter)) continue
const existing = seen.get(code)
if (!existing || year < existing.firstYear) {
seen.set(code, { airport, firstYear: year })
}
}
}
return [...seen.entries()]
.sort(([a], [b]) => a.localeCompare(b))
.map(([, entry]) => entry)
}
function isHighlighted({ firstYear }: AirportEntry): boolean {
return props.selectedYear !== null && firstYear === props.selectedYear
}
function toBBCode(): string {
return props.letters
.map(letter => {
const entries = airportEntriesForLetter(letter)
if (!entries.length) return letter
return entries
.map(entry => {
const code = getCode(entry.airport)!
return isHighlighted(entry) ? `[b][color=#00BF00]${code}[/color][/b]` : code
})
.join(', ')
})
.join('\n')
}
defineExpose({ toBBCode })
</script>
<template>
<BadgeTable
:rows="letters"
:rowKey="letter => letter"
:hasItems="letter => !!flightsByLetter[letter]?.length"
labelWidth="4em"
>
<template #label="{ row: letter }">
<div style="width:100%;display:flex;justify-content: center; align-items: center" :class="flightsByLetter[letter]?.length ? 'visited' : 'unvisited'">
{{ letter }}
</div>
</template>
<template #items="{ row: letter }">
<AirportToolTip
v-for="entry in airportEntriesForLetter(letter)"
:key="getCode(entry.airport)!"
:airport="entry.airport"
>
<InlineBadge :variant="isHighlighted(entry) ? 'business' : undefined">
{{ getCode(entry.airport) }}
</InlineBadge>
</AirportToolTip>
</template>
</BadgeTable>
</template>
<style scoped>
.visited {
font-weight: 700;
color: var(--accent);
}
.unvisited {
color: var(--muted);
}
.airport-count {
font-size: 0.7rem;
font-weight: 400;
color: var(--muted);
margin-left: 0.2em;
}
</style>