Improves reliability of link loading functionality: - Adds error state and handling for failed API requests - Implements retry mechanism with user-facing error message - Prevents infinite loading when errors occur - Defers search API call to mounted hook These changes enhance user experience by providing clear feedback and recovery options when link loading fails.
95 lines
2.1 KiB
Vue
95 lines
2.1 KiB
Vue
<script setup>
|
|
import { Loader } from 'lucide-vue-next'
|
|
import { useInfiniteScroll } from '@vueuse/core'
|
|
|
|
const links = ref([])
|
|
const limit = 24
|
|
let cursor = ''
|
|
let listComplete = false
|
|
let listError = false
|
|
|
|
async function getLinks() {
|
|
try {
|
|
const data = await useAPI('/api/link/list', {
|
|
query: {
|
|
limit,
|
|
cursor,
|
|
},
|
|
})
|
|
links.value = links.value.concat(data.links).filter(Boolean) // Sometimes cloudflare will return null, filter out
|
|
cursor = data.cursor
|
|
listComplete = data.list_complete
|
|
listError = false
|
|
}
|
|
catch (error) {
|
|
console.error(error)
|
|
listError = true
|
|
}
|
|
}
|
|
|
|
const { isLoading } = useInfiniteScroll(
|
|
document,
|
|
getLinks,
|
|
{
|
|
distance: 150,
|
|
interval: 1000,
|
|
canLoadMore: () => {
|
|
return !listError && !listComplete
|
|
},
|
|
},
|
|
)
|
|
|
|
function updateLinkList(link, type) {
|
|
if (type === 'edit') {
|
|
const index = links.value.findIndex(l => l.id === link.id)
|
|
links.value[index] = link
|
|
}
|
|
else if (type === 'delete') {
|
|
const index = links.value.findIndex(l => l.id === link.id)
|
|
links.value.splice(index, 1)
|
|
}
|
|
else {
|
|
links.value.unshift(link)
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<main class="space-y-6">
|
|
<div class="flex flex-col gap-6 sm:gap-2 sm:flex-row sm:justify-between">
|
|
<DashboardNav class="flex-1">
|
|
<DashboardLinksEditor @update:link="updateLinkList" />
|
|
</DashboardNav>
|
|
<LazyDashboardLinksSearch />
|
|
</div>
|
|
<section class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
|
|
<DashboardLinksLink
|
|
v-for="link in links"
|
|
:key="link.id"
|
|
:link="link"
|
|
@update:link="updateLinkList"
|
|
/>
|
|
</section>
|
|
<div
|
|
v-if="isLoading"
|
|
class="flex items-center justify-center"
|
|
>
|
|
<Loader class="animate-spin" />
|
|
</div>
|
|
<div
|
|
v-if="!isLoading && listComplete"
|
|
class="flex items-center justify-center text-sm"
|
|
>
|
|
No more
|
|
</div>
|
|
<div
|
|
v-if="listError"
|
|
class="flex items-center justify-center text-sm"
|
|
>
|
|
Loading links failed,
|
|
<Button variant="link" @click="getLinks">
|
|
Try again
|
|
</Button>
|
|
</div>
|
|
</main>
|
|
</template>
|