Files
evilspins/app/app.vue
valere f59c496c5d
All checks were successful
Deploy App / build (push) Successful in 2m25s
Deploy App / deploy (push) Successful in 15s
route v1
2025-10-21 00:09:26 +02:00

97 lines
2.6 KiB
Vue

<template>
<div>
<NuxtRouteAnnouncer />
<NuxtPage />
<SearchModal />
<Loader />
<!-- Persistent audio player across routes -->
<Player />
<!-- Mobile-only floating search button -->
<button v-if="$isMobile" @click="ui.openSearch()"
class="fixed bottom-4 right-4 z-50 inline-flex h-12 w-12 items-center justify-center rounded-full bg-esyellow text-slate-800 shadow-lg ring-1 ring-slate-300 hover:brightness-95 active:brightness-90 dark:ring-slate-600"
aria-label="Rechercher">
<svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="11" cy="11" r="8" />
<path d="m21 21-4.3-4.3" />
</svg>
</button>
</div>
</template>
<script setup>
import SearchModal from '~/components/SearchModal.vue'
import Player from '~/components/player.vue'
import Loader from '~/components/Loader.vue'
import { useUiStore } from '~/store/ui'
import { usePlayerStore } from '~/store/player'
import { watch, computed } from 'vue'
const ui = useUiStore()
const player = usePlayerStore()
const { $isMobile } = useNuxtApp()
useHead({
bodyAttrs: {
class: 'bg-slate-100 dark:bg-slate-900'
}
})
const router = useRouter()
const route = useRoute()
watch(
() => player.currentTrack?.id,
(id) => {
if (!id) {
if (route.name === 'track-id') router.replace({ path: '/' })
return
}
const currentParam = Number(
Array.isArray(route.params.id) ? route.params.id[0] : route.params.id
)
if (route.name === 'track-id' && currentParam === id) return
router.replace({ name: 'track-id', params: { id } })
},
{ flush: 'post' }
)
// Keep URL in sync with selected box: /box/:id when a box is selected, back to / when none
const selectedBoxId = computed(() => ui.getSelectedBox?.id)
watch(
() => selectedBoxId.value,
(id) => {
if (process.client) {
if (!id) {
// Back to root path without navigation to preserve UI state/animations
if (location.pathname.startsWith('/box/')) {
history.replaceState(null, '', '/')
}
return
}
const currentId = location.pathname.startsWith('/box/') ? location.pathname.split('/').pop() : null
if (currentId === id) return
requestAnimationFrame(() => {
history.replaceState(null, '', `/box/${id}`)
})
}
},
{ flush: 'post' }
)
</script>
<style>
button,
input {
@apply px-4 py-2 m-4 rounded-md text-center font-bold
}
button {
@apply bg-esyellow text-slate-700;
}
input[type="email"] {
@apply bg-slate-900 text-esyellow;
}
</style>