♠♣♦♥
All checks were successful
Deploy App / build (push) Successful in 2m29s
Deploy App / deploy (push) Successful in 15s

This commit is contained in:
valere
2025-10-11 09:56:14 +02:00
parent 2135b0fec6
commit 4d424eee54
4 changed files with 33 additions and 10 deletions

View File

@@ -2,8 +2,18 @@
<article @click="() => playerStore.playTrack(props.track).catch(err => console.error(err))" <article @click="() => playerStore.playTrack(props.track).catch(err => console.error(err))"
class="card flip-card w-56 h-80" :class="isFaceUp ? 'face-up' : 'face-down'"> class="card flip-card w-56 h-80" :class="isFaceUp ? 'face-up' : 'face-down'">
<div class="flip-inner"> <div class="flip-inner">
<!-- Face-Up -->
<main <main
class="flip-front backdrop-blur-sm border-2 -mt-12 z-10 card w-56 h-80 p-3 bg-opacity-40 hover:bg-opacity-80 hover:shadow-xl transition-all bg-white rounded-2xl shadow-lg flex flex-col overflow-hidden"> class="flip-front backdrop-blur-sm border-2 -mt-12 z-10 card w-56 h-80 p-3 bg-opacity-40 hover:bg-opacity-80 hover:shadow-xl transition-all bg-white rounded-2xl shadow-lg flex flex-col overflow-hidden">
<div class="flex items-center justify-center size-7 absolute top-7 right-7" v-if="isPlaylistTrack">
<div class="suit text-7xl absolute"
:class="[isRedCard ? 'text-red-600' : 'text-slate-800', props.track.card?.suit]">
{{ props.track.card?.suit }}
</div>
<div class="rank text-white font-bold absolute -mt-1">
{{ props.track.card?.rank }}
</div>
</div>
<!-- Cover --> <!-- Cover -->
<figure class="flex-1 overflow-hidden rounded-t-xl cursor-pointer"> <figure class="flex-1 overflow-hidden rounded-t-xl cursor-pointer">
<img :src="coverUrl" alt="Pochette de l'album" class="w-full h-full object-cover object-center" /> <img :src="coverUrl" alt="Pochette de l'album" class="w-full h-full object-cover object-center" />
@@ -14,22 +24,20 @@
<div class="label" v-if="isOrder"> <div class="label" v-if="isOrder">
{{ props.track.order }} {{ props.track.order }}
</div> </div>
<h2 class="text-base text-neutral-800 font-bold truncate">{{ props.track.title }}</h2> <h2 class="text-base text-neutral-800 font-bold truncate">
{{ props.track.title }}
</h2>
<p class="text-sm text-neutral-500 truncate"> <p class="text-sm text-neutral-500 truncate">
<template v-if="isPlaylistTrack"> <template v-if="isPlaylistTrack">
{{ props.track.artist.name }} {{ props.track.artist.name }}
</template> </template>
<div class="order" v-if="isPlaylistTrack">
{{ props.track.card?.rank }}
{{ props.track.card?.suit }}
</div>
</p> </p>
</div> </div>
</main> </main>
<!-- Face-Down -->
<footer <footer
class="flip-back backdrop-blur-sm -mt-12 z-10 card w-56 h-80 p-3 bg-opacity-10 bg-white rounded-2xl shadow-lg flex flex-col overflow-hidden"> class="flip-back backdrop-blur-sm -mt-12 z-10 card w-56 h-80 p-3 bg-opacity-10 bg-white rounded-2xl shadow-lg flex flex-col overflow-hidden">
<!-- Back -->
<div class="h-full flex p-16 text-center bg-slate-800 rounded-xl"> <div class="h-full flex p-16 text-center bg-slate-800 rounded-xl">
<img src="/favicon.svg" /> <img src="/favicon.svg" />
<div class="label label--id" v-if="isOrder"> <div class="label label--id" v-if="isOrder">
@@ -53,6 +61,7 @@ const playerStore = usePlayerStore()
const isManifesto = computed(() => props.track.compilationId.startsWith('ES00')) const isManifesto = computed(() => props.track.compilationId.startsWith('ES00'))
const isOrder = computed(() => props.track.order && !isManifesto) const isOrder = computed(() => props.track.order && !isManifesto)
const isPlaylistTrack = computed(() => props.track.compilationId.length === 6) const isPlaylistTrack = computed(() => props.track.compilationId.length === 6)
const isRedCard = computed(() => props.track.card?.suit === '♥' || props.track.card?.suit === '♦')
const coverUrl = props.track.coverId.startsWith('http') const coverUrl = props.track.coverId.startsWith('http')
? props.track.coverId ? props.track.coverId
: `https://f4.bcbits.com/img/${props.track.coverId}_4.jpg`; : `https://f4.bcbits.com/img/${props.track.coverId}_4.jpg`;
@@ -101,5 +110,21 @@ const coverUrl = props.track.coverId.startsWith('http')
.flip-back { .flip-back {
transform: rotateY(180deg); transform: rotateY(180deg);
} }
. {
@apply -mt-2;
}
. {
@apply text-7xl -mt-2;
}
. {
@apply -mt-3;
}
. {
@apply text-5xl
}
} }
</style> </style>

View File

@@ -5,7 +5,6 @@
{{ Math.round(currentTime) }} {{ Math.round(currentTime) }}
{{ Math.round(currentProgression) }}% {{ Math.round(currentProgression) }}%
</p> --> </p> -->
{{ playerStore.currentTrack?.url }}
<audio ref="audioRef" class="w-full" :src="playerStore.currentTrack?.url || ''" controls /> <audio ref="audioRef" class="w-full" :src="playerStore.currentTrack?.url || ''" controls />
</div> </div>
</template> </template>

View File

@@ -7,7 +7,6 @@
</main> </main>
</div> </div>
</template> </template>
<style> <style>
.logo { .logo {
filter: drop-shadow(2px 2px 0 rgb(0 0 0 / 0.8)); filter: drop-shadow(2px 2px 0 rgb(0 0 0 / 0.8));

View File

@@ -13,7 +13,7 @@ export default eventHandler(async (event) => {
const urlPrefix = `https://files.erudi.fr/music` const urlPrefix = `https://files.erudi.fr/music`
let files = await fs.promises.readdir(dirPath) let files = await fs.promises.readdir(dirPath)
files = files.filter((f) => !f.startsWith('.')) files = files.filter((f) => !f.startsWith('.') && !f.endsWith('.jpg'))
const tracks = files.map((file, index) => { const tracks = files.map((file, index) => {
const EXT_RE = /\.(mp3|flac|wav|opus)$/i const EXT_RE = /\.(mp3|flac|wav|opus)$/i
@@ -43,7 +43,7 @@ export default eventHandler(async (event) => {
const date = new Date(year, month - 1, day, hour) const date = new Date(year, month - 1, day, hour)
const card = getCardFromDate(date) const card = getCardFromDate(date)
const url = `${urlPrefix}/${encodeURIComponent(file)}` const url = `${urlPrefix}/${encodeURIComponent(file)}`
const coverId = `${urlPrefix}/cover/${encodeURIComponent(file)}` const coverId = `${urlPrefix}/${encodeURIComponent(file).replace(EXT_RE, '.jpg')}`
return { return {
id: Number(`${year}${index + 1}`), id: Number(`${year}${index + 1}`),