Files
FlightsAPI/resources/js/Components/FlightsGoneBy/Charts/FlightsPerYearChart.vue
T
2026-04-11 17:30:16 +10:00

119 lines
2.8 KiB
Vue

<template>
<div class="chart-wrap">
<div class="chart-title">Flights per year</div>
<apexchart
type="bar"
height="220"
:options="chartOptions"
:series="series"
/>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import type { Flight } from '@/Types/types'
const props = defineProps<{
flights: Flight[]
upcomingFlights: Flight[]
}>()
const years = computed(() => {
const allYears = new Set<number>()
;[...props.flights, ...props.upcomingFlights].forEach(f =>
allYears.add(new Date(f.departure_date).getFullYear())
)
const sorted = [...allYears].sort((a, b) => a - b)
let min = sorted[0]
let max = sorted[sorted.length - 1]
while (max - min + 1 < 5) {
min--
if (max - min + 1 < 5) max++
}
return Array.from({ length: max - min + 1 }, (_, i) => min + i)
})
const countByYear = (list: Flight[]) =>
years.value.map(year =>
list.filter(f => new Date(f.departure_date).getFullYear() === year).length
)
const series = computed(() => [
{ name: 'Flown', data: countByYear(props.flights) },
{ name: 'Upcoming', data: countByYear(props.upcomingFlights) },
])
const chartOptions = computed(() => ({
chart: {
type: 'bar',
stacked: true,
toolbar: { show: false },
background: 'transparent',
fontFamily: 'inherit',
},
theme: { mode: 'dark' },
plotOptions: {
bar: {
borderRadius: 3,
borderRadiusWhenStacked: 'last',
columnWidth: '55%',
},
},
colors: ['#4da6ff', '#ffc107'],
dataLabels: { enabled: false },
grid: {
borderColor: 'rgba(255,255,255,0.05)',
yaxis: { lines: { show: true } },
xaxis: { lines: { show: false } },
},
xaxis: {
categories: years.value,
axisBorder: { show: false },
axisTicks: { show: false },
labels: {
style: { colors: '#445566', fontSize: '12px' },
},
},
yaxis: {
labels: {
style: { colors: '#445566', fontSize: '12px' },
},
},
legend: {
position: 'top',
horizontalAlign: 'right',
labels: { colors: '#778899' },
markers: { width: 8, height: 8, radius: 2 },
itemMargin: { horizontal: 12 },
},
tooltip: {
theme: 'dark',
shared: true,
intersect: false,
},
states: {
hover: { filter: { type: 'lighten', value: 0.1 } },
active: { filter: { type: 'none' } },
},
}))
</script>
<style scoped>
.chart-wrap {
display: flex;
flex-direction: column;
gap: 4px;
}
.chart-title {
font-size: 13px;
font-weight: 500;
color: #556677;
text-transform: uppercase;
letter-spacing: 0.08em;
}
</style>