Added Notifications

This commit is contained in:
2026-05-18 14:31:53 +10:00
parent 1d5b9f340f
commit 10b5b6a5c9
18 changed files with 545 additions and 166 deletions
+57 -31
View File
@@ -1,11 +1,13 @@
<script setup lang="ts">
import {computed} from "vue"
import { ref, computed } from "vue"
import ProfileLayout from "@/Components/FlightsGoneBy/ProfileLayout.vue"
import ProfileViewSwitcher from "@/Components/FlightsGoneBy/ProfileViewSwitcher.vue"
import AchievementCard from "@/Components/FlightsGoneBy/AchievementCard.vue"
import {Achievement, User, UserAchievement} from "@/Types/types"
import { Head } from "@inertiajs/vue3";
import MainLayout from "@/Layouts/MainLayout.vue";
import Panel from "@/Components/FlightsGoneBy/Panels/Panel.vue";
import PanelHeader from "@/Components/FlightsGoneBy/Panels/PanelHeader.vue";
defineOptions({ layout: MainLayout })
@@ -15,21 +17,39 @@ const props = defineProps<{
isFollowing: boolean
achievements: Record<string, Achievement[]>
userAchievements: Record<number, UserAchievement>
unlockedCount: number
totalAchievements: number
unlockedByCategory: Record<string, number>
}>()
const totalAchievements = computed(() =>
Object.values(props.achievements).reduce((sum, group) => sum + group.length, 0)
const hideImpossible = ref(false)
const filteredAchievements = computed(() => {
if (!hideImpossible.value) return props.achievements
return Object.fromEntries(
Object.entries(props.achievements).map(([category, achievements]) => [
category,
achievements.filter(a => a.difficulty?.internal_name !== 'impossible')
])
)
})
const filteredUnlockedByCategory = computed(() =>
Object.fromEntries(
Object.entries(filteredAchievements.value).map(([category, achievements]) => [
category,
achievements.filter(a => props.userAchievements[a.id]?.unlocked).length
])
)
)
const unlockedCount = computed(() =>
Object.values(props.achievements)
.flat()
.filter(a => {
const ua = props.userAchievements[a.id]
if (!ua) return false
if (!a.progressive || !a.threshold) return true
return (ua.progress ?? 0) >= a.threshold
}).length
const filteredTotal = computed(() =>
Object.values(filteredAchievements.value).reduce((sum, group) => sum + group.length, 0)
)
const filteredUnlockedCount = computed(() =>
Object.values(filteredUnlockedByCategory.value).reduce((sum, count) => sum + count, 0)
)
</script>
@@ -45,11 +65,20 @@ const unlockedCount = computed(() =>
<div class="achievements-page">
<div class="achievements-summary">
<span class="summary-text">
{{ unlockedCount }} / {{ totalAchievements }} achievements unlocked
</span>
<div class="summary-controls">
<span class="summary-text">
{{ filteredUnlockedCount }} / {{ filteredTotal }} achievements unlocked
</span>
<v-checkbox
v-model="hideImpossible"
label="Hide Impossible Achievements"
density="compact"
hide-details
color="amber"
/>
</div>
<v-progress-linear
:model-value="Math.round((unlockedCount / totalAchievements) * 100)"
:model-value="Math.round((filteredUnlockedCount / filteredTotal) * 100)"
color="amber"
rounded
height="6"
@@ -57,18 +86,17 @@ const unlockedCount = computed(() =>
/>
</div>
<div
v-for="(categoryAchievements, categoryName) in achievements"
<Panel
v-for="(categoryAchievements, categoryName) in filteredAchievements"
:key="categoryName"
class="achievement-category"
>
<div class="category-header">
<h2 class="category-name">{{ categoryName }}</h2>
<PanelHeader class="category-header">{{ categoryName }}
<span class="category-count">
{{ categoryAchievements.filter(a => userAchievements[a.id]).length }}
{{ filteredUnlockedByCategory[categoryName] ?? 0 }}
/ {{ categoryAchievements.length }}
</span>
</div>
</PanelHeader>
<div class="achievement-grid">
<AchievementCard
@@ -79,7 +107,7 @@ const unlockedCount = computed(() =>
:user-achievement="userAchievements[achievement.id]"
/>
</div>
</div>
</Panel>
</div>
</ProfileLayout>
</template>
@@ -101,6 +129,12 @@ const unlockedCount = computed(() =>
gap: 0.5rem;
}
.summary-controls {
display: flex;
align-items: center;
justify-content: space-between;
}
.summary-text {
font-size: 0.9rem;
opacity: 0.7;
@@ -120,14 +154,6 @@ const unlockedCount = computed(() =>
padding-bottom: 0.5rem;
}
.category-name {
font-size: 1.1rem;
font-weight: 700;
letter-spacing: 0.05em;
text-transform: uppercase;
opacity: 0.9;
}
.category-count {
font-size: 0.85rem;
opacity: 0.5;