Session api token validation
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
<script setup lang="ts">
|
||||
import {User} from "@/Types/types";
|
||||
|
||||
defineProps<{
|
||||
user: User
|
||||
}>()
|
||||
import {Link} from "@inertiajs/vue3";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="avatar">
|
||||
<Link :href="route('profile.view', { user: user?.name })">
|
||||
{{ user?.name?.charAt(0).toUpperCase() ?? '?' }}
|
||||
</Link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.avatar {
|
||||
width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
border-radius: 50%;
|
||||
background: rgba(99, 102, 241, 0.2);
|
||||
border: 1px solid rgba(99, 102, 241, 0.35);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
color: #818cf8;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -14,6 +14,7 @@ import FlightCancelledFeedItem from "@/Components/FlightsGoneBy/Feed/FlightCance
|
||||
import FlightImportedFeedItem from "@/Components/FlightsGoneBy/Feed/FlightImportedFeedItem.vue";
|
||||
import FlightMovedFeedItem from "@/Components/FlightsGoneBy/Feed/FlightMovedFeedItem.vue";
|
||||
import ButtonLink from "@/Components/FlightsGoneBy/ButtonLink.vue";
|
||||
import Avatar from "@/Components/FlightsGoneBy/Feed/Avatar.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
action: UserAction
|
||||
@@ -56,11 +57,7 @@ function timeAgo(dateStr: string): string {
|
||||
<template>
|
||||
<div class="feed-item glass glass-border">
|
||||
<div class="card-top">
|
||||
<div class="avatar">
|
||||
<Link :href="route('profile.view', { user: action.user?.name })">
|
||||
{{ action.user?.name?.charAt(0).toUpperCase() ?? '?' }}
|
||||
</Link>
|
||||
</div>
|
||||
<Avatar :user="action.user" />
|
||||
<div class="meta">
|
||||
<span class="name">
|
||||
<Link :href="route('profile.view', { user: action.user?.name })">
|
||||
@@ -110,21 +107,6 @@ function timeAgo(dateStr: string): string {
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
border-radius: 50%;
|
||||
background: rgba(99, 102, 241, 0.2);
|
||||
border: 1px solid rgba(99, 102, 241, 0.35);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 600;
|
||||
font-size: 0.9rem;
|
||||
color: #818cf8;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -171,7 +171,11 @@ function airportPopupHTML(airport: Airport): string {
|
||||
|
||||
function routePopupHTML(historical: Flight[], future: Flight[]): string {
|
||||
interface AirlineEntry { html: string; count: number }
|
||||
interface DirectionGroup { label: string; airlines: Map<string, AirlineEntry> }
|
||||
interface DirectionGroup {
|
||||
label: string
|
||||
airlines: Map<string, AirlineEntry>
|
||||
users: Map<number, { name: string }>
|
||||
}
|
||||
|
||||
const groupByDirection = (flights: Flight[]): DirectionGroup[] => {
|
||||
const groups = new Map<string, DirectionGroup>()
|
||||
@@ -180,13 +184,19 @@ function routePopupHTML(historical: Flight[], future: Flight[]): string {
|
||||
const key = `${flight.departure_airport.id}-${flight.arrival_airport.id}`
|
||||
const label = `${flight.departure_airport.municipality} to ${flight.arrival_airport.municipality}`
|
||||
|
||||
if (!groups.has(key)) groups.set(key, { label, airlines: new Map() })
|
||||
if (!groups.has(key)) groups.set(key, { label, airlines: new Map(), users: new Map() })
|
||||
|
||||
const group = groups.get(key)!
|
||||
|
||||
if (flight.user) {
|
||||
group.users.set(flight.user.id, { name: flight.user.name })
|
||||
}
|
||||
|
||||
if (!flight.airline) return
|
||||
|
||||
const { iata_code, logo_url, name } = flight.airline
|
||||
const airlineKey = iata_code ?? ''
|
||||
const airlines = groups.get(key)!.airlines
|
||||
const airlines = group.airlines
|
||||
|
||||
if (airlines.has(airlineKey)) {
|
||||
airlines.get(airlineKey)!.count++
|
||||
@@ -204,10 +214,20 @@ function routePopupHTML(historical: Flight[], future: Flight[]): string {
|
||||
return [...groups.values()]
|
||||
}
|
||||
|
||||
const renderUsers = (users: Map<number, { name: string }>): string => {
|
||||
if (!users.size) return ''
|
||||
|
||||
const badges = [...users.values()]
|
||||
.map(({ name }) => `<span class="rp-user-badge">${name}</span>`)
|
||||
.join('')
|
||||
|
||||
return `<div class="rp-users">${badges}</div>`
|
||||
}
|
||||
|
||||
const renderSection = (title: string, flights: Flight[]): string => {
|
||||
if (!flights.length) return ''
|
||||
|
||||
const rows = groupByDirection(flights).map(({ label, airlines }) => {
|
||||
const rows = groupByDirection(flights).map(({ label, airlines, users }) => {
|
||||
const airlineLines = [...airlines.values()]
|
||||
.map(({ html, count }) => count > 1
|
||||
? `<span style="display:inline-flex;align-items:center;gap:4px;">${html}<span style="color:#556677">(x${count})</span></span>`
|
||||
@@ -218,6 +238,7 @@ function routePopupHTML(historical: Flight[], future: Flight[]): string {
|
||||
<div class="rp-direction">
|
||||
<div class="rp-route">${label}</div>
|
||||
<div class="rp-airlines">${airlineLines || '—'}</div>
|
||||
${renderUsers(users)}
|
||||
</div>`
|
||||
}).join('')
|
||||
|
||||
@@ -778,13 +799,17 @@ export default defineComponent({
|
||||
position: relative;
|
||||
width: 100%;
|
||||
aspect-ratio: 16 / 9;
|
||||
max-height: 70vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.flight-map-wrapper { aspect-ratio: 7 / 10; }
|
||||
.flight-map-wrapper {
|
||||
aspect-ratio: 7 / 10;
|
||||
max-height: none;
|
||||
}
|
||||
}
|
||||
|
||||
.map-container { position: absolute; inset: 0; }
|
||||
@@ -860,6 +885,22 @@ export default defineComponent({
|
||||
.rp-airlines { font-size: 0.75rem; color: #778899; }
|
||||
.rp-divider { height: 1px; background: rgba(255,255,255,0.08); margin: 2px 0; }
|
||||
|
||||
.rp-users {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.rp-user-badge {
|
||||
font-size: 0.7rem;
|
||||
color: #c8cdd8;
|
||||
background: rgba(77,166,255,0.12);
|
||||
border: 1px solid rgba(77,166,255,0.25);
|
||||
border-radius: 999px;
|
||||
padding: 1px 8px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Map controls */
|
||||
.maplibregl-ctrl-group { background: rgba(10,14,22,0.85) !important; border: 1px solid rgba(255,255,255,0.08) !important; }
|
||||
.maplibregl-ctrl-group button { color: #a0b4c8 !important; }
|
||||
|
||||
@@ -7,13 +7,13 @@ type FollowStatus = 'following' | 'requested' | 'none'
|
||||
|
||||
const props = defineProps<{
|
||||
user: User
|
||||
followStatus: FollowStatus
|
||||
followStatus: string
|
||||
}>()
|
||||
|
||||
const snackbar = ref(false)
|
||||
const snackbarMessage = ref('')
|
||||
|
||||
const status = ref<FollowStatus>(props.followStatus)
|
||||
const status = ref<FollowStatus>(props.followStatus as FollowStatus)
|
||||
const processing = ref(false)
|
||||
|
||||
const auth = usePage<SharedProps>().props.auth
|
||||
|
||||
@@ -11,6 +11,7 @@ const props = defineProps<{
|
||||
achievementCount?: number
|
||||
followStatus?: string
|
||||
show: "flights" | "achievements"
|
||||
showCount?: boolean
|
||||
}>()
|
||||
|
||||
const counts = computed(() => {
|
||||
@@ -39,7 +40,7 @@ const counts = computed(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="board-count">
|
||||
<div class="board-count" v-if="showCount">
|
||||
<span class="count-number">{{ counts[show] }}</span>
|
||||
<span class="count-label">{{show.toUpperCase()}}</span>
|
||||
</div>
|
||||
|
||||
@@ -13,13 +13,14 @@ defineProps<{
|
||||
loading: boolean
|
||||
canView: boolean
|
||||
title?: string
|
||||
showCount?: boolean
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="board-wrapper">
|
||||
<Head :title="title" />
|
||||
<ProfileHeader :show="achievementCount && achievementCount > 0 ? 'achievements' : 'flights'" :followStatus="followStatus" :user="user" :flightCount="flightCount" :achievementCount="achievementCount" />
|
||||
<ProfileHeader :showCount="showCount" :show="achievementCount && achievementCount > 0 ? 'achievements' : 'flights'" :followStatus="followStatus" :user="user" :flightCount="flightCount" :achievementCount="achievementCount" />
|
||||
<div v-if="loading" class="loading-state">
|
||||
<PlaneLoader />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user