Files
FlightsAPI/resources/js/Pages/FlightProfile.vue
T
2026-04-12 20:34:22 +10:00

182 lines
4.6 KiB
Vue

<script setup lang="ts">
import MainLayout from "@/Layouts/MainLayout.vue";
import { Head } from '@inertiajs/vue3';
import { Flight } from "@/Types/types";
import DepartureBoard from "@/Components/FlightsGoneBy/DepartureBoard.vue";
import BoardingPasses from "@/Components/FlightsGoneBy/BoardingPasses.vue";
import { ref } from "vue";
import ProfileMap from "@/Components/FlightsGoneBy/ProfileMap.vue";
defineOptions({
layout: MainLayout
})
defineProps<{
user: {
id: number
name: string
email: string
}
flights: Flight[]
canEdit: boolean
}>()
type View = 'board' | 'passes' | 'map'
const activeView = ref<View>('map')
</script>
<template>
<Head :title="`${user.name}'s Flights`" />
<div class="board-wrapper">
<div class="board-header">
<div class="board-title-group">
<span class="board-eyebrow">FLIGHT HISTORY</span>
<h1 class="board-title">{{ user.name }}</h1>
</div>
<div class="board-count">
<span class="count-number">{{ flights.length }}</span>
<span class="count-label">FLIGHTS</span>
</div>
</div>
<!-- View switcher toolbar -->
<div class="view-toolbar">
<button
class="view-btn"
:class="{ active: activeView === 'map' }"
@click="activeView = 'map'"
>
<span class="view-btn-icon mdi mdi-earth"></span>
<span class="view-btn-label">Map</span>
</button>
<button
class="view-btn"
:class="{ active: activeView === 'board' }"
@click="activeView = 'board'"
>
<span class="view-btn-icon mdi mdi-table"></span>
<span class="view-btn-label">DEPARTURE BOARD</span>
</button>
<button
class="view-btn"
:class="{ active: activeView === 'passes' }"
@click="activeView = 'passes'"
>
<span class="view-btn-icon mdi mdi-ticket"></span>
<span class="view-btn-label">BOARDING PASSES</span>
</button>
</div>
<DepartureBoard v-if="activeView === 'board'" :flights="flights" :canEdit="canEdit" />
<BoardingPasses v-else-if="activeView === 'passes'" :flights="flights" />
<ProfileMap v-else-if="activeView === 'map'" :flights="flights" />
</div>
</template>
<style scoped>
@import url('https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=Barlow:wght@400;500;600&family=Barlow+Condensed:wght@500;700&display=swap');
/* ── Wrapper ── */
.board-wrapper {
min-height: 100dvh;
padding: 2.5rem 2rem;
font-family: 'Barlow', sans-serif;
width: 100%;
}
/* ── Header ── */
.board-header {
display: flex;
align-items: flex-end;
justify-content: space-between;
margin-bottom: 2rem;
border-bottom: 1px solid rgba(255,193,7,0.2);
padding-bottom: 1.25rem;
}
.board-eyebrow {
display: block;
font-family: 'Share Tech Mono', monospace;
font-size: 0.7rem;
letter-spacing: 0.2em;
color: #ffc107;
margin-bottom: 0.25rem;
}
.board-title {
font-family: 'Barlow Condensed', sans-serif;
font-size: 2.2rem;
font-weight: 700;
color: #f0f2f5;
letter-spacing: 0.04em;
line-height: 1;
margin: 0;
}
.board-count {
text-align: right;
line-height: 1;
}
.count-number {
display: block;
font-family: 'Share Tech Mono', monospace;
font-size: 2rem;
color: #ffc107;
}
.count-label {
font-family: 'Share Tech Mono', monospace;
font-size: 0.65rem;
letter-spacing: 0.18em;
color: #556;
}
/* ── View toolbar ── */
.view-toolbar {
display: flex;
gap: 0;
margin-bottom: 1.5rem;
border: 1px solid rgba(255,193,7,0.15);
border-radius: 3px;
width: fit-content;
overflow: hidden;
}
.view-btn {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1.25rem;
background: transparent;
border: none;
border-right: 1px solid rgba(255,193,7,0.15);
color: #556;
font-family: 'Share Tech Mono', monospace;
font-size: 0.68rem;
letter-spacing: 0.15em;
cursor: pointer;
transition: background 0.15s, color 0.15s;
}
.view-btn:last-child {
border-right: none;
}
.view-btn:hover {
background: rgba(255,193,7,0.05);
color: #9aa;
}
.view-btn.active {
background: rgba(255,193,7,0.08);
color: #ffc107;
}
.view-btn-icon {
font-size: 0.8rem;
opacity: 0.8;
}
</style>