Skip to content

Commit bf288c9

Browse files
author
Joseph Shenton
committed
feat: update Dashboard to use both downloads and torrents APIs
- Fetch from /api/downloads in addition to /api/torrents - Show separate counts for Torrents and Downloads - Calculate combined total size from both sources - Combine recent activity from both torrents and downloads - Sort activity by date descending - Show source type (torrent/download) in activity list
1 parent 4186c20 commit bf288c9

1 file changed

Lines changed: 49 additions & 21 deletions

File tree

web/src/app/(dashboard)/page.tsx

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,17 @@ interface Torrent {
4242
seeds: number
4343
}
4444

45+
interface DownloadItem {
46+
id: string
47+
name: string
48+
type: string
49+
status: string
50+
progress: number
51+
size: number
52+
provider: string
53+
addedAt: string
54+
}
55+
4556
interface ServiceStatus {
4657
webhook: boolean
4758
poller: boolean
@@ -105,26 +116,30 @@ function getStatusBadgeVariant(status: string, progress: number): "default" | "s
105116
export default function DashboardPage() {
106117
const [providers, setProviders] = useState<Provider[]>([])
107118
const [torrents, setTorrents] = useState<Torrent[]>([])
119+
const [downloads, setDownloads] = useState<DownloadItem[]>([])
108120
const [services, setServices] = useState<ServiceStatus | null>(null)
109121
const [loading, setLoading] = useState(true)
110122
const [refreshing, setRefreshing] = useState(false)
111123

112124
async function fetchData() {
113125
try {
114-
const [providersRes, torrentsRes, statusRes] = await Promise.all([
126+
const [providersRes, torrentsRes, downloadsRes, statusRes] = await Promise.all([
115127
fetch("/api/providers"),
116128
fetch("/api/torrents"),
129+
fetch("/api/downloads"),
117130
fetch("/api/status"),
118131
])
119132

120-
const [providersData, torrentsData, statusData] = await Promise.all([
133+
const [providersData, torrentsData, downloadsData, statusData] = await Promise.all([
121134
providersRes.json(),
122135
torrentsRes.json(),
136+
downloadsRes.json(),
123137
statusRes.json(),
124138
])
125139

126140
if (providersData.ok !== false) setProviders(providersData.providers || [])
127141
if (torrentsData.ok !== false) setTorrents(torrentsData.torrents || [])
142+
if (downloadsData.ok !== false) setDownloads(downloadsData.downloads || [])
128143
if (statusData.ok !== false) setServices(statusData.services || null)
129144
} catch (error) {
130145
console.error("Failed to fetch dashboard data:", error)
@@ -146,13 +161,25 @@ export default function DashboardPage() {
146161
fetchData()
147162
}
148163

149-
// Calculate stats from real data
164+
// Calculate stats from real data - combine torrents + downloads
150165
const totalTorrents = torrents.length
166+
const totalDownloads = downloads.length
151167
const activeTorrents = torrents.filter(t =>
152168
t.progress < 100 && !t.status.toLowerCase().includes("error")
153169
).length
154-
const totalSize = torrents.reduce((acc, t) => acc + (t.size || 0), 0)
170+
const activeDownloads = downloads.filter(d =>
171+
d.progress < 100 && !d.status.toLowerCase().includes("error")
172+
).length
173+
const totalTorrentSize = torrents.reduce((acc, t) => acc + (t.size || 0), 0)
174+
const totalDownloadSize = downloads.reduce((acc, d) => acc + (d.size || 0), 0)
175+
const totalSize = totalTorrentSize + totalDownloadSize
155176
const connectedProviders = providers.filter(p => p.connected).length
177+
178+
// Combine recent activity from both sources
179+
const allActivity = [
180+
...torrents.map(t => ({ ...t, source: "torrent" as const })),
181+
...downloads.map(d => ({ ...d, source: "download" as const, seeds: 0, downloadSpeed: 0 })),
182+
].sort((a, b) => new Date(b.addedAt).getTime() - new Date(a.addedAt).getTime())
156183

157184
const servicesList = services ? [
158185
{ name: "Webhook Server", status: services.webhook ? "running" : "stopped", port: 8978 },
@@ -216,30 +243,29 @@ export default function DashboardPage() {
216243
<Card>
217244
<CardHeader className="flex flex-row items-center justify-between pb-2">
218245
<CardTitle className="text-sm font-medium text-muted-foreground">
219-
Total Torrents
246+
Torrents
220247
</CardTitle>
221248
<Download className="h-4 w-4 text-muted-foreground" />
222249
</CardHeader>
223250
<CardContent>
224251
<div className="text-2xl font-bold">{totalTorrents}</div>
225252
<p className="text-xs text-muted-foreground">
226-
Across all providers
253+
{activeTorrents > 0 ? `${activeTorrents} active` : "Across all providers"}
227254
</p>
228255
</CardContent>
229256
</Card>
230257

231258
<Card>
232259
<CardHeader className="flex flex-row items-center justify-between pb-2">
233260
<CardTitle className="text-sm font-medium text-muted-foreground">
234-
Active Transfers
261+
Downloads
235262
</CardTitle>
236263
<Activity className="h-4 w-4 text-muted-foreground" />
237264
</CardHeader>
238265
<CardContent>
239-
<div className="text-2xl font-bold">{activeTorrents}</div>
266+
<div className="text-2xl font-bold">{totalDownloads}</div>
240267
<p className="text-xs text-muted-foreground">
241-
In progress
242-
{activeTorrents > 0 && <span className="ml-2 text-blue-500">Live</span>}
268+
{activeDownloads > 0 ? `${activeDownloads} active` : "Ready to stream"}
243269
</p>
244270
</CardContent>
245271
</Card>
@@ -254,7 +280,7 @@ export default function DashboardPage() {
254280
<CardContent>
255281
<div className="text-2xl font-bold">{formatBytes(totalSize)}</div>
256282
<p className="text-xs text-muted-foreground">
257-
Across all torrents
283+
{totalTorrents + totalDownloads} items total
258284
</p>
259285
</CardContent>
260286
</Card>
@@ -286,29 +312,31 @@ export default function DashboardPage() {
286312
<CardDescription>Latest downloads and transfers</CardDescription>
287313
</CardHeader>
288314
<CardContent>
289-
{torrents.length === 0 ? (
315+
{allActivity.length === 0 ? (
290316
<div className="text-center py-8 text-muted-foreground">
291317
<Download className="h-8 w-8 mx-auto mb-2 opacity-50" />
292-
<p>No torrents found</p>
318+
<p>No activity found</p>
293319
<p className="text-sm">Add content to see activity here</p>
294320
</div>
295321
) : (
296322
<div className="space-y-4">
297-
{torrents.slice(0, 5).map((torrent) => (
298-
<div key={torrent.id} className="flex items-center justify-between">
323+
{allActivity.slice(0, 5).map((item) => (
324+
<div key={`${item.source}-${item.provider}-${item.id}`} className="flex items-center justify-between">
299325
<div className="flex items-center gap-3 min-w-0 flex-1">
300-
{getStatusIcon(torrent.status, torrent.progress)}
326+
{getStatusIcon(item.status, item.progress)}
301327
<div className="min-w-0 flex-1">
302-
<p className="text-sm font-medium truncate">{torrent.name}</p>
303-
<p className="text-xs text-muted-foreground capitalize">{torrent.provider}</p>
328+
<p className="text-sm font-medium truncate">{item.name}</p>
329+
<p className="text-xs text-muted-foreground capitalize">
330+
{item.provider}{item.source}
331+
</p>
304332
</div>
305333
</div>
306334
<div className="flex items-center gap-2 ml-2">
307-
<Badge variant={getStatusBadgeVariant(torrent.status, torrent.progress)}>
308-
{torrent.progress >= 100 ? "completed" : torrent.status}
335+
<Badge variant={getStatusBadgeVariant(item.status, item.progress)}>
336+
{item.progress >= 100 ? "completed" : item.status}
309337
</Badge>
310338
<span className="text-xs text-muted-foreground whitespace-nowrap">
311-
{formatRelativeTime(torrent.addedAt)}
339+
{formatRelativeTime(item.addedAt)}
312340
</span>
313341
</div>
314342
</div>

0 commit comments

Comments
 (0)