veza/apps/web/src/features/playlists
2025-12-26 09:11:46 +01:00
..
__tests__ [INT-AUTH-002] Remove duplicate auth store - migrate to features/auth/store/authStore.ts 2025-12-26 09:11:46 +01:00
components [INT-AUTH-002] Remove duplicate auth store - migrate to features/auth/store/authStore.ts 2025-12-26 09:11:46 +01:00
hooks [INT-AUTH-002] Remove duplicate auth store - migrate to features/auth/store/authStore.ts 2025-12-26 09:11:46 +01:00
pages [FE-PAGE-009] fe-page: Complete Playlist List page implementation 2025-12-24 13:05:21 +01:00
services [FE-COMP-017] fe-comp: Add playlist follow/unfollow button 2025-12-25 12:07:29 +01:00
styles refonte: backend-api go first; phase 1 2025-12-12 21:34:34 -05:00
utils refonte: backend-api go first; phase 1 2025-12-12 21:34:34 -05:00
README.md refonte: backend-api go first; phase 1 2025-12-12 21:34:34 -05:00
routes.tsx stabilizing apps/web: FIRST BATCH 2025-12-17 08:07:35 -05:00
types.ts [INT-TYPE-005] Create PlaylistVisibility enum aligned with backend 2025-12-25 22:36:51 +01:00

Feature: Playlists

Cette feature fournit tous les composants, hooks et services nécessaires pour gérer les playlists dans l'application VEZA.

Architecture

Structure des fichiers

features/playlists/
├── components/          # Composants UI
│   ├── PlaylistCard.tsx           # Carte d'affichage d'une playlist
│   ├── PlaylistList.tsx           # Liste de playlists avec pagination
│   ├── PlaylistHeader.tsx         # En-tête de détail de playlist
│   ├── PlaylistActions.tsx        # Actions (edit/delete) pour une playlist
│   ├── PlaylistForm.tsx           # Formulaire création/édition
│   ├── CreatePlaylistDialog.tsx   # Dialog de création
│   ├── PlaylistAnalytics.tsx      # Analytics d'une playlist
│   ├── PlaylistEditor.tsx         # Éditeur de playlist
│   └── PlaylistManager.tsx        # Gestionnaire de playlists
├── pages/               # Pages
│   ├── PlaylistListPage.tsx       # Page liste des playlists
│   ├── PlaylistDetailPage.tsx     # Page détail d'une playlist
│   ├── PlaylistCreatePage.tsx     # Page création
│   └── PlaylistEditPage.tsx       # Page édition
├── hooks/               # Hooks React
│   ├── usePlaylist.ts             # Hooks pour CRUD playlists et collaboration
│   └── usePlaylistPermissions.ts  # Hooks pour les permissions
├── services/            # Services
│   └── playlistService.ts         # Service API pour playlists
├── routes.tsx           # Routes React Router
├── types.ts             # Types TypeScript
├── __tests__/           # Tests d'intégration
│   ├── playlist.integration.test.tsx
│   └── collaboration.integration.test.tsx
└── index.ts             # Exports publics

Utilisation

Routes

Les routes sont configurées dans routes.tsx et intégrées dans le router principal :

  • /playlists - Liste des playlists
  • /playlists/new - Créer une nouvelle playlist
  • /playlists/:id - Détails d'une playlist
  • /playlists/:id/edit - Éditer une playlist

Composants principaux

Gestion des Tracks dans une Playlist

La page PlaylistDetailPage intègre tous les composants de gestion des tracks :

  • PlaylistTrackList : Affiche la liste des tracks avec numérotation, actions (play, remove) et drag-and-drop pour réorganiser
  • AddTrackToPlaylistModal : Modal pour rechercher et ajouter des tracks à la playlist
  • RemoveTrackButton : Bouton pour retirer un track de la playlist (intégré dans PlaylistTrackItem)

Fonctionnalités :

  • Affichage ordonné des tracks par position
  • Drag-and-drop pour réorganiser les tracks
  • Ajout de tracks via modal de recherche
  • Suppression de tracks avec confirmation
  • Lecture des tracks directement depuis la playlist
  • Synchronisation avec le player global

Exemple d'utilisation :

<PlaylistTrackList
  playlistTracks={playlistTracks}
  tracks={tracks}
  playlistId={playlistId}
  onTrackClick={handleTrackClick}
  onTrackPlay={handleTrackPlay}
  onTrackRemoved={handleTrackRemoved}
  onTracksReordered={handleTracksReordered}
  isPlaying={checkIsPlaying}
  currentPlayingId={currentTrack?.id}
  enableDragAndDrop={true}
/>

PlaylistList

Affiche une liste de playlists avec pagination et vue grille/liste.

import { PlaylistList } from '@/features/playlists';

<PlaylistList view="grid" limit={20} />;

PlaylistCard

Carte d'affichage d'une playlist individuelle.

import { PlaylistCard } from '@/features/playlists';

<PlaylistCard playlist={playlist} />;

PlaylistForm

Formulaire réutilisable pour créer ou éditer une playlist.

import { PlaylistForm } from '@/features/playlists';

// Création
<PlaylistForm onSubmit={handleCreate} onCancel={handleCancel} />

// Édition
<PlaylistForm playlist={playlist} onSubmit={handleUpdate} onCancel={handleCancel} />

PlaylistDetailPage

Page complète de détail d'une playlist avec header, actions et liste des tracks.

import { PlaylistDetailPage } from '@/features/playlists';

// Utilisé via les routes : /playlists/:id

Hooks

usePlaylist

Récupère une playlist par son ID.

import { usePlaylist } from '@/features/playlists';

const { data: playlist, isLoading, error } = usePlaylist(playlistId);

usePlaylists

Récupère la liste des playlists avec pagination.

import { usePlaylists } from '@/features/playlists';

const { data, isLoading, error } = usePlaylists(limit, offset);

useCreatePlaylist

Hook de mutation pour créer une playlist.

import { useCreatePlaylist } from '@/features/playlists';

const createMutation = useCreatePlaylist();

await createMutation.mutateAsync({
  title: 'My Playlist',
  description: 'Description',
  is_public: true,
});

useUpdatePlaylist

Hook de mutation pour mettre à jour une playlist.

import { useUpdatePlaylist } from '@/features/playlists';

const updateMutation = useUpdatePlaylist();

await updateMutation.mutateAsync({
  id: 1,
  data: {
    title: 'Updated Title',
    description: 'Updated description',
  },
});

useDeletePlaylist

Hook de mutation pour supprimer une playlist.

import { useDeletePlaylist } from '@/features/playlists';

const deleteMutation = useDeletePlaylist();

await deleteMutation.mutateAsync(playlistId);

Services

playlistService

Service API pour toutes les opérations CRUD.

import {
  createPlaylist,
  getPlaylist,
  updatePlaylist,
  deletePlaylist,
  listPlaylists,
} from '@/features/playlists';

// Créer
const playlist = await createPlaylist({
  title: 'My Playlist',
  description: 'Description',
  is_public: true,
});

// Lire
const playlist = await getPlaylist(1);
const playlists = await listPlaylists(20, 0);

// Mettre à jour
const updated = await updatePlaylist(1, {
  title: 'Updated Title',
});

// Supprimer
await deletePlaylist(1);

Types

import type {
  Playlist,
  PlaylistTrack,
  CreatePlaylistRequest,
  UpdatePlaylistRequest,
  PlaylistListResponse,
} from '@/features/playlists';

Fonctionnalités

CRUD complet

  • Création de playlists
  • Lecture (liste et détail)
  • Mise à jour
  • Suppression

Interface utilisateur

  • Vue grille et liste
  • Pagination
  • Filtres et recherche
  • Actions (edit/delete) avec vérification d'ownership
  • Modals de confirmation

Validation

  • Validation des formulaires avec zod
  • Messages d'erreur en français
  • Validation côté client et serveur

Tests

  • Tests unitaires pour tous les composants
  • Tests d'intégration CRUD
  • Coverage ≥ 80%

Dépendances

  • React Router pour la navigation
  • React Query pour la gestion des données
  • Zustand pour l'état d'authentification
  • Zod pour la validation
  • React Hook Form pour les formulaires

Notes

  • Les playlists sont liées à un utilisateur (user_id)
  • Seul le propriétaire peut modifier/supprimer sa playlist
  • Les playlists peuvent être publiques ou privées
  • Les playlists peuvent contenir des tracks (PlaylistTrack)