Files
FlightsAPI/resources/js/Components/FlightsGoneBy/AirlineAlphabetTable.vue
T
2026-05-19 21:45:24 +10:00

113 lines
3.2 KiB
Vue

<script setup lang="ts">
import { Flight, Airline } from '@/Types/types'
import type { CodeType } from '@/Composables/useAlphabetAirlines'
import BadgeTable from '@/Components/FlightsGoneBy/GenericBadgeTable.vue'
import InlineBadge from '@/Components/FlightsGoneBy/InlineBadge.vue'
import AirlineLogo from "@/Components/FlightsGoneBy/AirlineLogo.vue";
const props = defineProps<{
letters: string[]
flightsByLetter: Record<string, Flight[]>
codeType: CodeType
selectedYear: number | null
}>()
interface AirlineEntry {
airline: Airline
code: string
firstYear: number
}
function getCode(airline: Airline): string | null {
const raw = props.codeType === 'iata' ? airline.IATA_code : airline.ICAO_code
return raw?.trim().toUpperCase() ?? null
}
function airlineEntriesForLetter(letter: string): AirlineEntry[] {
const flights = props.flightsByLetter[letter] ?? []
const seen = new Map<number, AirlineEntry>() // key by airline.id
for (const flight of flights) {
const airline = flight.airline
if (!airline) continue
const code = getCode(airline)
if (!code?.startsWith(letter)) continue
const year = new Date(flight.departure_date).getFullYear()
const existing = seen.get(airline.id)
if (!existing || year < existing.firstYear) {
seen.set(airline.id, { airline, code, firstYear: year })
}
}
return [...seen.values()]
.sort((a, b) => a.code.localeCompare(b.code))
.map(entry => entry)
}
function isHighlighted({ firstYear }: AirlineEntry): boolean {
return props.selectedYear !== null && firstYear === props.selectedYear
}
function toBBCode(): string {
return props.letters
.map(letter => {
const entries = airlineEntriesForLetter(letter)
if (!entries.length) return letter
return entries
.map(entry =>
isHighlighted(entry)
? `[b][color=#00BF00]${entry.code}[/color][/b]`
: entry.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 }">
<div
v-for="entry in airlineEntriesForLetter(letter)"
:key="entry.airline.id"
>
<InlineBadge style="align-items:center;gap:0.2em" :variant="isHighlighted(entry) ? 'business' : undefined">
<AirlineLogo :airline="entry.airline" /> {{ entry.code }}
</InlineBadge>
</div>
</template>
</BadgeTable>
</template>
<style scoped>
.visited {
font-weight: 700;
color: var(--accent);
}
.unvisited {
color: var(--muted);
}
</style>