d35605ab73
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
71 lines
2.2 KiB
Vue
71 lines
2.2 KiB
Vue
<template>
|
|
<v-container fluid class="py-6">
|
|
<FilterPills v-model="pill" />
|
|
|
|
<v-alert v-if="store.error" type="error" variant="tonal" closable class="my-4">
|
|
{{ String(store.error) }}
|
|
</v-alert>
|
|
|
|
<div v-if="store.loading && store.events.length === 0" class="fc-dl__loading">
|
|
<v-progress-circular indeterminate color="accent" size="36" />
|
|
</div>
|
|
|
|
<div v-else-if="store.events.length === 0" class="fc-dl__empty">
|
|
<p>No download events yet. Trigger a check from /subscriptions.</p>
|
|
</div>
|
|
|
|
<div v-else>
|
|
<DownloadEventRow
|
|
v-for="e in store.events" :key="e.id" :event="e"
|
|
@open="openDetail"
|
|
/>
|
|
<div class="fc-dl__sentinel">
|
|
<v-btn v-if="store.hasMore" variant="text" @click="store.loadMore()" :loading="store.loading">
|
|
Load more
|
|
</v-btn>
|
|
<span v-else class="text-caption" style="opacity: 0.5">No more events.</span>
|
|
</div>
|
|
</div>
|
|
|
|
<DownloadDetailModal
|
|
:event="store.selected"
|
|
@close="store.closeDetail()"
|
|
/>
|
|
</v-container>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { onMounted, ref, watch } from 'vue'
|
|
import { useDownloadsStore } from '../stores/downloads.js'
|
|
import FilterPills from '../components/downloads/FilterPills.vue'
|
|
import DownloadEventRow from '../components/downloads/DownloadEventRow.vue'
|
|
import DownloadDetailModal from '../components/downloads/DownloadDetailModal.vue'
|
|
|
|
const store = useDownloadsStore()
|
|
const pill = ref('all')
|
|
|
|
onMounted(() => store.loadFirst())
|
|
|
|
watch(pill, async (v) => {
|
|
// 'quarantined' has no API filter yet — defer until the API grows
|
|
// (a metadata.run_stats.quarantined_count > 0 filter, FC-3d territory).
|
|
// For now route it the same as 'all' but keep the chip for discoverability.
|
|
const statusMap = { all: null, running: 'running', error: 'error', quarantined: null }
|
|
await store.applyFilter({ status: statusMap[v] })
|
|
})
|
|
|
|
async function openDetail(id) {
|
|
await store.loadOne(id)
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.fc-dl__loading, .fc-dl__empty {
|
|
display: flex; justify-content: center; padding: 3rem 0;
|
|
color: rgb(var(--v-theme-on-surface-variant));
|
|
}
|
|
.fc-dl__sentinel {
|
|
display: flex; justify-content: center; padding: 1rem 0;
|
|
}
|
|
</style>
|