refactor(links): extract sort menu and fix sort logic
- Extracts dropdown sort menu into separate DashboardLinksSort component - Fixes incorrect sort order for newest/oldest links - Adds internationalization support for sort options - Updates QR code download button size for consistency - Adds helpful tooltip about sort limitation for loaded links The sort logic was reversed where newest/oldest were concerned, this fixes that while making the sorting feature more maintainable through component extraction.
This commit is contained in:
parent
71c726ab9b
commit
5118201911
5 changed files with 75 additions and 40 deletions
|
|
@ -1,27 +1,22 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from '#components'
|
|
||||||
import { useInfiniteScroll } from '@vueuse/core'
|
import { useInfiniteScroll } from '@vueuse/core'
|
||||||
import { ArrowUpDown, Loader } from 'lucide-vue-next'
|
import { Loader } from 'lucide-vue-next'
|
||||||
|
|
||||||
const links = ref([])
|
const links = ref([])
|
||||||
const limit = 24
|
const limit = 24
|
||||||
let cursor = ''
|
let cursor = ''
|
||||||
let listComplete = false
|
let listComplete = false
|
||||||
let listError = false
|
let listError = false
|
||||||
const sortBy = ref('newest')
|
|
||||||
|
const sortBy = ref('az')
|
||||||
|
|
||||||
const displayedLinks = computed(() => {
|
const displayedLinks = computed(() => {
|
||||||
const sorted = [...links.value]
|
const sorted = [...links.value]
|
||||||
switch (sortBy.value) {
|
switch (sortBy.value) {
|
||||||
case 'newest':
|
case 'newest':
|
||||||
return sorted.sort((a, b) => b.createdAt - a.createdAt)
|
|
||||||
case 'oldest':
|
|
||||||
return sorted.sort((a, b) => a.createdAt - b.createdAt)
|
return sorted.sort((a, b) => a.createdAt - b.createdAt)
|
||||||
|
case 'oldest':
|
||||||
|
return sorted.sort((a, b) => b.createdAt - a.createdAt)
|
||||||
case 'az':
|
case 'az':
|
||||||
return sorted.sort((a, b) => a.slug.localeCompare(b.slug))
|
return sorted.sort((a, b) => a.slug.localeCompare(b.slug))
|
||||||
case 'za':
|
case 'za':
|
||||||
|
|
@ -83,33 +78,7 @@ function updateLinkList(link, type) {
|
||||||
<DashboardNav class="flex-1">
|
<DashboardNav class="flex-1">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<DashboardLinksEditor @update:link="updateLinkList" />
|
<DashboardLinksEditor @update:link="updateLinkList" />
|
||||||
<DropdownMenu>
|
<DashboardLinksSort v-model:sort-by="sortBy" />
|
||||||
<DropdownMenuTrigger as-child>
|
|
||||||
<Button variant="outline" size="sm">
|
|
||||||
<ArrowUpDown class="mr-2 h-4 w-4" />
|
|
||||||
Sort by: {{
|
|
||||||
sortBy === 'newest' ? 'Newest First'
|
|
||||||
: sortBy === 'oldest' ? 'Oldest First'
|
|
||||||
: sortBy === 'az' ? 'Slug A-Z'
|
|
||||||
: 'Slug Z-A'
|
|
||||||
}}
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent>
|
|
||||||
<DropdownMenuItem @click="sortBy = 'newest'">
|
|
||||||
Newest First
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem @click="sortBy = 'oldest'">
|
|
||||||
Oldest First
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem @click="sortBy = 'az'">
|
|
||||||
A to Z
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem @click="sortBy = 'za'">
|
|
||||||
Z to A
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
</div>
|
</div>
|
||||||
</DashboardNav>
|
</DashboardNav>
|
||||||
<LazyDashboardLinksSearch />
|
<LazyDashboardLinksSearch />
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,11 @@ onMounted(() => {
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button variant="outline" @click="downloadQRCode">
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
@click="downloadQRCode"
|
||||||
|
>
|
||||||
<Download class="w-4 h-4 mr-2" />
|
<Download class="w-4 h-4 mr-2" />
|
||||||
{{ $t('links.download_qr_code') }}
|
{{ $t('links.download_qr_code') }}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
48
components/dashboard/links/Sort.vue
Normal file
48
components/dashboard/links/Sort.vue
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
<script setup>
|
||||||
|
import { ArrowUpDown } from 'lucide-vue-next'
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
sortBy: {
|
||||||
|
type: String,
|
||||||
|
default: 'az',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:sortBy'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger as-child>
|
||||||
|
<Button variant="outline">
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger class="flex items-center">
|
||||||
|
<ArrowUpDown class="h-4 w-4 sm:mr-2" />
|
||||||
|
<span class="hidden sm:inline">
|
||||||
|
{{ $t('links.sort.newest') }}
|
||||||
|
</span>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>{{ $t('links.sort.tip') }}</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent>
|
||||||
|
<DropdownMenuItem @click="emit('update:sortBy', 'newest')">
|
||||||
|
{{ $t('links.sort.newest') }}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem @click="emit('update:sortBy', 'oldest')">
|
||||||
|
{{ $t('links.sort.oldest') }}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem @click="emit('update:sortBy', 'az')">
|
||||||
|
{{ $t('links.sort.az') }}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem @click="emit('update:sortBy', 'za')">
|
||||||
|
{{ $t('links.sort.za') }}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</template>
|
||||||
|
|
@ -157,6 +157,13 @@
|
||||||
"expires_at": "Expires At",
|
"expires_at": "Expires At",
|
||||||
"no_more": "No more links",
|
"no_more": "No more links",
|
||||||
"load_failed": "Loading links failed,",
|
"load_failed": "Loading links failed,",
|
||||||
"download_qr_code": "Download QR Code"
|
"download_qr_code": "Download QR Code",
|
||||||
|
"sort": {
|
||||||
|
"newest": "Newest First",
|
||||||
|
"oldest": "Oldest First",
|
||||||
|
"az": "Slug A-Z",
|
||||||
|
"za": "Slug Z-A",
|
||||||
|
"tip": "Experience: Only for loaded links"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,13 @@
|
||||||
"expires_at": "过期时间",
|
"expires_at": "过期时间",
|
||||||
"no_more": "没有更多链接",
|
"no_more": "没有更多链接",
|
||||||
"load_failed": "加载链接失败,",
|
"load_failed": "加载链接失败,",
|
||||||
"download_qr_code": "下载二维码"
|
"download_qr_code": "下载二维码",
|
||||||
|
"sort": {
|
||||||
|
"newest": "最新",
|
||||||
|
"oldest": "最旧",
|
||||||
|
"az": "字母(A-Z)",
|
||||||
|
"za": "字母(Z-A)",
|
||||||
|
"tip": "体验功能: 仅对已经加载的链接有效"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue