playlists support v1
All checks were successful
Deploy App / build (push) Successful in 4m19s
Deploy App / deploy (push) Successful in 16s

This commit is contained in:
valere
2025-10-09 22:47:30 +02:00
parent c86e345117
commit e2c5693948
30 changed files with 620 additions and 554 deletions

View File

@@ -5,10 +5,11 @@ import { defineStore } from 'pinia'
export const useDataStore = defineStore('data', {
state: () => ({
compilations: [] as Compilation[], // Store your compilation data here
artists: [] as Artist[], // Store artist data here
tracks: [] as Track[], // Store track data here
isLoaded: false, // Remember if data is already loaded
compilations: [] as Compilation[], // Store your compilation data here
artists: [] as Artist[], // Store artist data here
tracks: [] as Track[], // Store track data here
playlistTracks: [] as Track[], // store playslit tracks
isLoaded: false // Remember if data is already loaded
}),
actions: {
@@ -17,18 +18,32 @@ export const useDataStore = defineStore('data', {
const { data: compilations } = await useFetch<Compilation[]>('/api/compilations')
const { data: artists } = await useFetch<Artist[]>('/api/artists')
const { data: rawTracks } = await useFetch<{ id: number, compilationId: string, title: string, artist: number, start: number, url: string, coverId: string }[]>('/api/tracks')
const { data: rawTracks } = await useFetch<Track[]>('/api/tracks')
const { data: playlistTracks } = await useFetch<Track[]>('/api/playlists')
// Stocker les données de base
this.compilations = compilations.value ?? []
this.artists = artists.value ?? []
// Mapper les tracks pour remplacer l'artistId par l'objet Artist
const artistMap = new Map(this.artists.map(a => [a.id, a]))
this.tracks = (rawTracks.value ?? []).map(track => ({
const artistMap = new Map(this.artists.map((a) => [a.id, a]))
this.tracks = (rawTracks.value ?? []).map((track) => ({
...track,
artist: artistMap.get(track.artist) ?? { id: track.artist, name: 'Unknown', url: '', coverId: '' }
artist: artistMap.get(track.artist) ?? {
id: track.artist,
name: 'Unknown',
url: '',
coverId: ''
}
}))
this.playlistTracks = (playlistTracks.value ?? []).map((track) => ({
...track,
artist: artistMap.get(track.artist) ?? {
id: track.artist,
name: track.artist,
url: '',
coverId: ''
}
}))
this.isLoaded = true
@@ -40,34 +55,43 @@ export const useDataStore = defineStore('data', {
getAllCompilations: (state) => state.compilations,
getCompilationById: (state) => {
return (id: string) => {
return state.compilations.find(compilation => compilation.id === id)
return state.compilations.find((compilation) => compilation.id === id)
}
},
// Obtenir toutes les pistes d'une compilation donnée
getTracksByCompilationId: (state) => (compilationId: string) => {
return state.tracks.filter(track => track.compilationId === compilationId)
getTracksByCompilationId: (state) => (id: string) => {
return state.tracks.filter((track) => track.compilationId === id)
},
// Filtrer les artistes selon certains critères
getArtistById: (state) => (id: number) => state.artists.find(artist => artist.id === id),
getArtistById: (state) => (id: number) => state.artists.find((artist) => artist.id === id),
// Obtenir toutes les pistes d'un artiste donné
getTracksByArtistId: (state) => (artistId: number) => {
return state.tracks.filter(track => track.artist.id === artistId)
return state.tracks.filter((track) => track.artist.id === artistId)
},
getFirstTrackOfCompilation() {
return (compilationId: string) => {
const tracks = this.getTracksByCompilationId(compilationId)
return tracks.length > 0 ? tracks[0] : null
}
},
getNextTrack: (state) => {
return (track: Track) => {
// Récupérer toutes les tracks de la même compilation et les trier par ordre
const tracksInCompilation = state.tracks
.filter(t => t.compilationId === track.compilationId)
.filter((t) => t.compilationId === track.compilationId)
.sort((a, b) => a.order - b.order)
// Trouver lindex de la track courante
const index = tracksInCompilation.findIndex(t => t.id === track.id)
const index = tracksInCompilation.findIndex((t) => t.id === track.id)
// Retourner la track suivante ou null si cest la dernière
return index >= 0 && index < tracksInCompilation.length - 1
? tracksInCompilation[index + 1]
: null
}
},
getPlaylistTracksByCompilationId: (state) => (id: string) => {
return state.playlistTracks.filter((track) => track.compilationId === id)
}
},
}
})

View File

@@ -7,11 +7,12 @@ export const usePlayerStore = defineStore('player', {
state: () => ({
currentTrack: null as Track | null,
position: 0,
audio: null as HTMLAudioElement | null,
audio: null as HTMLAudioElement | null
}),
actions: {
async playTrack(track: Track) {
const oldTrack = this.currentTrack
this.currentTrack = track
// toggle si on reclique sur la même
@@ -24,21 +25,20 @@ export const usePlayerStore = defineStore('player', {
}
// définir la source (fichier de la compilation entière)
this.audio.src = this.getCompilationUrlFromTrack(track)
this.audio.load()
// attendre que le player soit prêt avant de lire
await new Promise<void>((resolve, reject) => {
const onCanPlay = () => {
this.audio!.removeEventListener("canplay", onCanPlay)
this.audio!.removeEventListener('canplay', onCanPlay)
resolve()
}
const onError = (e: Event) => {
this.audio!.removeEventListener("error", onError)
this.audio!.removeEventListener('error', onError)
reject(e)
}
this.audio!.addEventListener("canplay", onCanPlay, { once: true })
this.audio!.addEventListener("error", onError, { once: true })
this.audio!.addEventListener('canplay', onCanPlay, { once: true })
this.audio!.addEventListener('error', onError, { once: true })
})
// positionner le début
@@ -48,24 +48,23 @@ export const usePlayerStore = defineStore('player', {
try {
await this.audio.play()
} catch (err) {
console.error("Impossible de lire la piste :", err)
console.error('Impossible de lire la piste :', err)
}
},
togglePlay() {
if (!this.audio) return
if (this.audio.paused) {
this.audio.play().catch(err => console.error(err))
this.audio.play().catch((err) => console.error(err))
} else {
this.audio.pause()
}
},
}
},
getters: {
isCurrentCompilation: (state) => {
return (compilationId: string) =>
compilationId === state.currentTrack?.compilationId
return (compilationId: string) => compilationId === state.currentTrack?.compilationId
},
isPlayingTrack: (state) => {
@@ -85,15 +84,8 @@ export const usePlayerStore = defineStore('player', {
getCurrentTrack: (state) => state.currentTrack,
getCompilationUrlFromTrack: () => {
return (track: Track) =>
`https://files.erudi.fr/evilspins/${track.compilationId}.mp3`
},
getCurrentCompilation: (state) => {
return state.currentTrack
? state.getCompilationUrlFromTrack(state.currentTrack)
: null
return state.currentTrack ? state.currentTrack.url : null
},
getTrackStop: (state) => {
@@ -109,5 +101,5 @@ export const usePlayerStore = defineStore('player', {
}
}
}
},
}
})

11
app/store/user.ts Normal file
View File

@@ -0,0 +1,11 @@
import type { Compilation, Artist, Track } from '~/../types/types'
// stores/user.ts
import { defineStore } from 'pinia'
export const useDataStore = defineStore('data', {
state: () => ({
badge: [] // un badge par user achievement pour enrichir le déchifrage de l'app (afichage des nom des titres/artiste, collection de carte déjà joué (et du coups possibilité de les rejouer dans son deck))
// evilSpins est un jeux mais pas vraiment pokemon (un morceau = un pokemon) mais aussi un jeux d'aventure / exploration ou plus on progresse plus on peu voir de chose
})
})