import { useState } from 'react';
import { useNavigate } from 'react-router';
import { useTranslation } from 'react-i18next';
import {
Tabs,
TabsList,
TabsContent,
SearchField,
ScrollArea,
Card,
} from '@olly/modern-sk';
import {
useGetTracksQuery,
useGetAlbumsQuery,
useGetArtistsQuery,
} from '../../api/endpoints/library';
import { TrackRow } from '../../components/track/TrackRow';
import { LoadingSkeleton } from '../../components/common/LoadingSkeleton';
import { EmptyState } from '../../components/common/EmptyState';
import { ErrorState } from '../../components/common/ErrorState';
import { useAppDispatch } from '../../hooks/useAppDispatch';
import { setQueue } from '../../store/slices/queue';
import type { Track, Album, Artist } from '../../api/types';
import { getCoverUrl } from '../../api/endpoints/streaming';
import { formatDuration } from '../../lib/format';
export function LibraryPage() {
const { t } = useTranslation();
const navigate = useNavigate();
const dispatch = useAppDispatch();
const [tab, setTab] = useState('tracks');
const [search, setSearch] = useState('');
const tracksQuery = useGetTracksQuery(search ? { search } : undefined);
const albumsQuery = useGetAlbumsQuery(search ? { search } : undefined);
const artistsQuery = useGetArtistsQuery(search ? { search } : undefined);
const handlePlayAll = (tracks: Track[]) => {
dispatch(
setQueue({
entries: tracks.map((t) => ({
trackId: t.id,
title: t.title,
artistName: t.artistName,
albumTitle: t.albumTitle,
durationMs: t.durationMs,
albumArtUrl: t.albumArtUrl,
})),
source: 'manual',
sourceName: t('library.title'),
}),
);
};
return (
{t('library.title')}
setSearch(e.target.value)}
placeholder={t('library.searchPlaceholder')}
icon="⌕"
/>
{tracksQuery.isLoading && }
{tracksQuery.isError && (
tracksQuery.refetch()} />
)}
{tracksQuery.data && tracksQuery.data.items.length === 0 && (
)}
{tracksQuery.data &&
tracksQuery.data.items.length > 0 &&
(() => {
const data = tracksQuery.data!;
return (
{data.items.map((track, i) => (
))}
);
})()}
{albumsQuery.isLoading && }
{albumsQuery.isError && (
albumsQuery.refetch()} />
)}
{albumsQuery.data && albumsQuery.data.items.length === 0 && (
)}
{albumsQuery.data && (
{albumsQuery.data.items.map((album) => (
void navigate(`/albums/${album.id}`)}
/>
))}
)}
{artistsQuery.isLoading && }
{artistsQuery.isError && (
artistsQuery.refetch()} />
)}
{artistsQuery.data && artistsQuery.data.items.length === 0 && (
)}
{artistsQuery.data && (
{artistsQuery.data.items.map((artist) => (
))}
)}
);
}
function AlbumCard({ album, onClick }: { album: Album; onClick: () => void }) {
const { t } = useTranslation();
const artUrl = getCoverUrl(album.artUrl);
return (
{artUrl ? (
) : (
💿
)}
{album.title}
{album.artistName}
{t('library.albumCard.tracksDuration', {
count: album.trackCount,
duration: formatDuration(album.totalDurationMs),
})}
);
}
function ArtistRow({ artist }: { artist: Artist }) {
const { t } = useTranslation();
return (
🎤
{artist.name}
{t('library.artistRow.meta', {
albumCount: artist.albumCount,
trackCount: artist.trackCount,
})}
);
}