Add Fix My Playlist feature

New endpoint POST /api/playlists/{id}/fix that analyzes a playlist
using Claude AI to identify outlier tracks that don't match the
overall vibe, and suggests better-fitting replacements.

Frontend shows results with warm amber cards for outliers and green
cards for replacements, with dismissible suggestions and visual
highlighting of flagged tracks in the track list.
This commit is contained in:
root
2026-03-31 08:43:20 -05:00
parent cf2d8019bb
commit 47ab3dd847
4 changed files with 319 additions and 4 deletions

View File

@@ -97,6 +97,7 @@ export interface RecommendationItem {
image_url: string | null
spotify_url: string | null
bandcamp_url: string | null
youtube_url: string | null
reason: string
saved: boolean
disliked: boolean
@@ -175,6 +176,7 @@ export const generateRecommendations = (
mode?: string,
adventurousness?: number,
exclude?: string,
count?: number,
) =>
api.post<RecommendationResponse>('/recommendations/generate', {
playlist_id: playlistId,
@@ -183,6 +185,7 @@ export const generateRecommendations = (
mode: mode || 'discover',
adventurousness: adventurousness ?? 3,
exclude: exclude || undefined,
count: count ?? 5,
}).then((r) => r.data)
export const getRecommendationHistory = () =>
@@ -278,6 +281,30 @@ export async function getBandcampEmbed(url: string): Promise<BandcampEmbed> {
return data
}
// Playlist Fix
export interface OutlierTrack {
track_number: number
artist: string
title: string
reason: string
}
export interface ReplacementTrack {
title: string
artist: string
album: string | null
reason: string
}
export interface PlaylistFixResponse {
playlist_vibe: string
outliers: OutlierTrack[]
replacements: ReplacementTrack[]
}
export const fixPlaylist = (playlistId: string) =>
api.post<PlaylistFixResponse>(`/playlists/${playlistId}/fix`).then((r) => r.data)
// Taste Profile
export const getTasteProfile = () =>
api.get<TasteProfileResponse>('/profile/taste').then((r) => r.data)