mirror of
https://github.com/markuryy/shark.git
synced 2025-12-13 12:01:01 +00:00
feat(wip): search
This commit is contained in:
94
src/lib/components/SearchResultsTable.svelte
Normal file
94
src/lib/components/SearchResultsTable.svelte
Normal file
@@ -0,0 +1,94 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import type { SearchResult, SearchType } from '$lib/types/search';
|
||||
|
||||
interface Props {
|
||||
results: SearchResult[];
|
||||
searchType: SearchType;
|
||||
onDownload?: (result: SearchResult) => void;
|
||||
}
|
||||
|
||||
let { results, searchType, onDownload }: Props = $props();
|
||||
|
||||
let selectedIndex = $state<number | null>(null);
|
||||
|
||||
function handleRowClick(index: number) {
|
||||
selectedIndex = index;
|
||||
}
|
||||
|
||||
function handleRowDoubleClick(result: SearchResult, index: number) {
|
||||
if (searchType === 'local') {
|
||||
// Navigate to album view
|
||||
if (result.artistName && result.albumTitle) {
|
||||
const artistEncoded = encodeURIComponent(result.artistName);
|
||||
const albumEncoded = encodeURIComponent(result.albumTitle);
|
||||
goto(`/albums/${artistEncoded}/${albumEncoded}`);
|
||||
}
|
||||
} else if (searchType === 'online') {
|
||||
// Trigger download
|
||||
if (onDownload) {
|
||||
onDownload(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function formatDuration(seconds?: number): string {
|
||||
if (!seconds) return '—';
|
||||
const mins = Math.floor(seconds / 60);
|
||||
const secs = Math.floor(seconds % 60);
|
||||
return `${mins}:${secs.toString().padStart(2, '0')}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="table-container">
|
||||
<table class="interactive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Track</th>
|
||||
<th>Artist</th>
|
||||
<th>Duration</th>
|
||||
<th>Album</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each results as result, i}
|
||||
<tr
|
||||
class:highlighted={selectedIndex === i}
|
||||
onclick={() => handleRowClick(i)}
|
||||
ondblclick={() => handleRowDoubleClick(result, i)}
|
||||
>
|
||||
<td>{result.title}</td>
|
||||
<td>{result.artist}</td>
|
||||
<td class="duration">{formatDuration(result.duration)}</td>
|
||||
<td>{result.album}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.table-container {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.duration {
|
||||
font-family: monospace;
|
||||
text-align: center;
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
td:last-child {
|
||||
opacity: 0.7;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user