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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user