diff --git a/src/components/player/Player.tsx b/src/components/player/Player.tsx
index 3e41019..809915a 100644
--- a/src/components/player/Player.tsx
+++ b/src/components/player/Player.tsx
@@ -504,7 +504,7 @@ export function Player({ className, onPlayerModeChange }: PlayerProps) {
{/* Main Player Area */}
{/* Large Album Art */}
-
+
{state.current_sound?.thumbnail ? (
})
(null)
const [trackStatistics, setTrackStatistics] = useState
(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
+
+ // Top sounds state
+ const [topSounds, setTopSounds] = useState([])
+ const [topSoundsLoading, setTopSoundsLoading] = useState(false)
+ const [soundType, setSoundType] = useState('SDB')
+ const [period, setPeriod] = useState('all_time')
+ const [limit, setLimit] = useState(5)
+
+ const fetchTopSounds = async () => {
+ try {
+ setTopSoundsLoading(true)
+ const response = await fetch(
+ `/api/v1/dashboard/top-sounds?sound_type=${soundType}&period=${period}&limit=${limit}`,
+ { credentials: 'include' }
+ )
+
+ if (!response.ok) {
+ throw new Error('Failed to fetch top sounds')
+ }
+
+ const data = await response.json()
+ setTopSounds(data)
+ } catch (err) {
+ console.error('Failed to fetch top sounds:', err)
+ } finally {
+ setTopSoundsLoading(false)
+ }
+ }
useEffect(() => {
const fetchStatistics = async () => {
@@ -52,6 +90,10 @@ export function DashboardPage() {
fetchStatistics()
}, [])
+
+ useEffect(() => {
+ fetchTopSounds()
+ }, [soundType, period, limit])
if (loading) {
return (
@@ -268,6 +310,108 @@ export function DashboardPage() {
+
+ {/* Top Sounds Section */}
+
+
+
+
+
+
+ Top Sounds
+
+
+
+ Type:
+
+
+
+ Period:
+
+
+
+ Count:
+
+
+
+
+
+
+ {topSoundsLoading ? (
+
+
+ Loading top sounds...
+
+ ) : topSounds.length === 0 ? (
+
+
+
No sounds found for the selected criteria
+
+ ) : (
+
+ {topSounds.map((sound, index) => (
+
+
+ {index + 1}
+
+
+
+
{sound.name}
+
+
+
+ {sound.play_count} plays
+
+ {sound.duration && (
+
+
+ {formatDuration(sound.duration)}
+
+ )}
+
+ {sound.type}
+
+
+
+
+ ))}
+
+ )}
+
+
+
diff --git a/src/pages/PlaylistEditPage.tsx b/src/pages/PlaylistEditPage.tsx
index 04455d2..79bad7d 100644
--- a/src/pages/PlaylistEditPage.tsx
+++ b/src/pages/PlaylistEditPage.tsx
@@ -606,25 +606,17 @@ export function PlaylistEditPage() {
// If it's an EXT sound and we're in add mode, add it back to available sounds
if (isAddMode && removedSound.type === 'EXT') {
- // Convert PlaylistSound back to Sound format for available list
- const soundToAddBack = {
- id: removedSound.id,
- name: removedSound.name,
- filename: removedSound.filename,
- duration: removedSound.duration,
- size: removedSound.size,
- hash: removedSound.hash,
- type: removedSound.type,
- play_count: removedSound.play_count,
- is_normalized: removedSound.is_normalized,
- normalized_filename: removedSound.normalized_filename,
- normalized_duration: removedSound.normalized_duration,
- normalized_size: removedSound.normalized_size,
- normalized_hash: removedSound.normalized_hash,
- created_at: removedSound.created_at,
- updated_at: removedSound.updated_at
+ // Fetch the complete sound data to add back to available sounds
+ try {
+ const allExtSounds = await soundsService.getSoundsByType('EXT')
+ const soundToAddBack = allExtSounds.find(s => s.id === soundId)
+ if (soundToAddBack) {
+ setAvailableSounds(prev => [...prev, soundToAddBack].sort((a, b) => a.name.localeCompare(b.name)))
+ }
+ } catch {
+ // If we can't fetch the sound data, just refresh the available sounds
+ await fetchAvailableSounds()
}
- setAvailableSounds(prev => [...prev, soundToAddBack].sort((a, b) => a.name.localeCompare(b.name)))
}
// Optimistically update playlist stats