156 lines
4.0 KiB
Vue
156 lines
4.0 KiB
Vue
<script setup lang="ts">
|
|
import { usePage } from "@inertiajs/vue3";
|
|
import { computed, ref } from "vue";
|
|
import type { Flight, User, SharedProps } from "@/Types/types";
|
|
|
|
const props = defineProps<{
|
|
user: User
|
|
flightCount?: number
|
|
achievementCount?: number
|
|
isFollowing?: boolean
|
|
}>()
|
|
|
|
const auth = usePage<SharedProps>().props.auth
|
|
const isOwnProfile = computed(() => auth.user?.id == props.user.id)
|
|
const isLoggedIn = computed(() => !!auth.user)
|
|
|
|
const following = ref(props.isFollowing ?? false)
|
|
const processing = ref(false)
|
|
const snackbar = ref(false)
|
|
const snackbarMessage = ref('')
|
|
|
|
const follow = async () => {
|
|
processing.value = true
|
|
const response = await fetch(route('profile.follow', { user: props.user.name }), {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') ?? '',
|
|
},
|
|
})
|
|
const data = await response.json()
|
|
following.value = data.following
|
|
snackbarMessage.value = data.following ? `You are now following ${props.user.name}` : `You unfollowed ${props.user.name}`
|
|
snackbar.value = true
|
|
processing.value = false
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="board-header">
|
|
<div class="board-left">
|
|
<div class="board-title-group">
|
|
<span class="board-eyebrow">FLIGHT HISTORY</span>
|
|
<div class="board-title-row">
|
|
<h1 class="board-title">{{ user.name }}</h1>
|
|
<button
|
|
v-if="isLoggedIn && !isOwnProfile"
|
|
class="follow-btn"
|
|
:disabled="processing"
|
|
@click="follow"
|
|
>
|
|
{{ following ? 'Following' : '+ Follow' }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="board-count">
|
|
<span class="count-number">{{ flightCount ?? achievementCount }}</span>
|
|
<span class="count-label">{{flightCount ? 'Flights' : 'Achievements'}}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<v-snackbar v-model="snackbar" :timeout="5000" color="#ffc107" location="bottom center">
|
|
{{ snackbarMessage }}
|
|
<template #actions>
|
|
<v-btn variant="text" @click="snackbar = false">Close</v-btn>
|
|
</template>
|
|
</v-snackbar>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.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-left {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.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-row {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
}
|
|
|
|
.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;
|
|
}
|
|
|
|
.follow-btn {
|
|
font-family: 'Share Tech Mono', monospace;
|
|
font-size: 0.75rem;
|
|
letter-spacing: 0.12em;
|
|
color: #ffc107;
|
|
background: none;
|
|
border: 1px solid rgba(255, 193, 7, 0.35);
|
|
border-radius: 4px;
|
|
padding: 0.3em 0.85em;
|
|
cursor: pointer;
|
|
transition: background 0.15s ease;
|
|
white-space: nowrap;
|
|
align-self: center;
|
|
}
|
|
|
|
.follow-btn:hover:not(:disabled) {
|
|
background: rgba(255, 193, 7, 0.1);
|
|
}
|
|
|
|
.follow-btn:disabled {
|
|
opacity: 0.5;
|
|
cursor: default;
|
|
}
|
|
|
|
.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;
|
|
text-transform: uppercase;
|
|
}
|
|
</style>
|