Added achievement data

This commit is contained in:
2026-04-28 22:16:21 +10:00
parent 14aed7bf6e
commit b94b1d8ec2
43 changed files with 1559 additions and 130 deletions
@@ -0,0 +1,198 @@
<!-- AchievementCard.vue -->
<script setup lang="ts">
import {Achievement, BadgeVariant, UserAchievement} from "@/Types/types";
import {computed} from "vue";
import InlineBadge from "@/Components/FlightsGoneBy/InlineBadge.vue";
import GlassTooltip from "@/Components/FlightsGoneBy/GlassTooltip.vue";
const props = defineProps<{
achievement: Achievement
userAchievement?: UserAchievement
}>()
const progress = computed(() => {
if (!props.achievement.progressive || !props.achievement.threshold) return null
const current = props.userAchievement?.progress ?? 0
return {
current,
threshold: props.achievement.threshold,
percentage: Math.min(Math.round((current / props.achievement.threshold) * 100), 100)
}
})
const unlocked = computed(() => {
if (!props.userAchievement) return false
if (props.achievement.progressive) return (progress.value?.percentage ?? 0) >= 100
return true
})
const difficultyVariant = computed(() => {
switch (props.achievement.difficulty?.internal_name) {
case 'easy': return 'easy'
case 'moderate': return 'moderate'
case 'hard': return 'hard'
case 'expensive': return 'expensive'
case 'near_impossible': return 'near-impossible'
case 'impossible': return 'impossible'
default: return 'economy'
}
})
</script>
<template>
<v-card
class="achievement-card"
:class="{ locked: !unlocked }"
rounded="lg"
elevation="2"
>
<v-card-text>
<div class="achievement-inner">
<div class="achievement-icon-wrap" :class="{ unlocked }">
<v-icon
icon="mdi-trophy"
:color="unlocked ? 'amber' : 'grey'"
size="28"
/>
</div>
<div class="achievement-content">
<div class="achievement-header">
<span class="achievement-name">{{ achievement.name }}</span>
<GlassTooltip>
<template #activator="{ props: tooltipProps }">
<span v-bind="tooltipProps" style="display:inline-flex">
<InlineBadge type="difficulty" :variant="difficultyVariant">
{{ achievement.difficulty?.name }}&nbsp;
<v-icon icon="mdi-help-circle-outline" size="12" />
</InlineBadge>
</span>
</template>
<div class="difficulty-tooltip">
<InlineBadge type="difficulty" :variant="difficultyVariant">
{{ achievement.difficulty?.name }}
</InlineBadge>
<p class="difficulty-description">{{ achievement.difficulty?.description }}</p>
<p v-if="achievement.difficulty_description" class="difficulty-description specific">
{{ achievement.difficulty_description }}
</p>
</div>
</GlassTooltip>
</div>
<p class="achievement-description">{{ achievement.short_description }}</p>
<template v-if="achievement.progressive && progress">
<div class="progress-label">
<span>{{ Math.min(progress.current, progress.threshold) }} / {{ progress.threshold }}</span>
<span>{{ progress.percentage }}%</span>
</div>
<v-progress-linear
:model-value="progress.percentage"
:color="unlocked ? 'amber' : 'grey'"
rounded
height="6"
bg-color="rgba(255,255,255,0.1)"
/>
</template>
</div>
</div>
</v-card-text>
</v-card>
</template>
<style scoped>
.achievement-card {
transition: opacity 0.2s ease, transform 0.2s ease;
}
.achievement-card.locked {
opacity: 0.45;
}
.achievement-card:hover {
opacity: 1;
transform: translateY(-1px);
}
.achievement-inner {
display: flex;
gap: 1rem;
align-items: flex-start;
}
.achievement-icon-wrap {
display: flex;
align-items: center;
justify-content: center;
width: 48px;
height: 48px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.05);
flex-shrink: 0;
}
.achievement-icon-wrap.unlocked {
background: rgba(255, 193, 7, 0.15);
}
.achievement-content {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.35rem;
}
.achievement-header {
display: flex;
align-items: center;
gap: 0.5rem;
flex-wrap: wrap;
}
.achievement-name {
font-weight: 600;
font-size: 0.95rem;
}
.achievement-description {
font-size: 0.82rem;
opacity: 0.75;
margin: 0;
}
.progress-label {
display: flex;
justify-content: space-between;
font-size: 0.75rem;
opacity: 0.6;
}
.difficulty-tooltip {
display: flex;
flex-direction: column;
gap: 0.4rem;
max-width: 240px;
}
.difficulty-description {
margin: 0;
font-size: 0.78rem;
line-height: 1.4;
opacity: 0.8;
}
.difficulty-description.specific {
display: flex;
align-items: flex-start;
gap: 0.3rem;
opacity: 0.65;
font-style: italic;
padding-top: 0.25rem;
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
</style>