Skip to content

Commit b474c7d

Browse files
committed
feat: add "Least downloaded" and "Least recently updated" sort options
This PR adds two new sort options: - Least downloaded - Least recently updated Disclaimer: AI generated translations (GPT 5.2 used)
1 parent 0d06026 commit b474c7d

File tree

16 files changed

+103
-44
lines changed

16 files changed

+103
-44
lines changed

app/components/PackageListControls.vue

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
<script setup lang="ts">
2-
export type SortOption = 'downloads' | 'updated' | 'name-asc' | 'name-desc'
2+
export type SortOption =
3+
| 'downloads-desc'
4+
| 'downloads-asc'
5+
| 'updated-desc'
6+
| 'updated-asc'
7+
| 'name-asc'
8+
| 'name-desc'
39
410
const props = defineProps<{
511
/** Current search/filter text */
@@ -32,8 +38,10 @@ const sortValue = computed({
3238
const sortOptions = computed(
3339
() =>
3440
[
35-
{ value: 'downloads', label: $t('package.sort.downloads') },
36-
{ value: 'updated', label: $t('package.sort.updated') },
41+
{ value: 'downloads-desc', label: $t('package.sort.downloads_desc') },
42+
{ value: 'downloads-asc', label: $t('package.sort.downloads_asc') },
43+
{ value: 'updated-desc', label: $t('package.sort.updated_desc') },
44+
{ value: 'updated-asc', label: $t('package.sort.updated_asc') },
3745
{ value: 'name-asc', label: $t('package.sort.name_asc') },
3846
{ value: 'name-desc', label: $t('package.sort.name_desc') },
3947
] as const,

app/pages/~[username]/index.vue

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,40 @@ const updateUrl = debounce((updates: { page?: number; filter?: string; sort?: st
2424
...route.query,
2525
page: updates.page && updates.page > 1 ? updates.page : undefined,
2626
q: updates.filter || undefined,
27-
sort: updates.sort && updates.sort !== 'downloads' ? updates.sort : undefined,
27+
sort: updates.sort && updates.sort !== 'downloads-desc' ? updates.sort : undefined,
2828
},
2929
})
3030
}, 300)
3131
32-
type SortOption = 'downloads' | 'updated' | 'name-asc' | 'name-desc'
32+
type SortOption =
33+
| 'downloads-desc'
34+
| 'downloads-asc'
35+
| 'updated-desc'
36+
| 'updated-asc'
37+
| 'name-asc'
38+
| 'name-desc'
3339
3440
// Filter and sort state (from URL)
3541
const filterText = shallowRef(
3642
(Array.isArray(route.query.q) ? route.query.q[0] : route.query.q) ?? '',
3743
)
38-
const sortOption = shallowRef<SortOption>(
39-
((Array.isArray(route.query.sort) ? route.query.sort[0] : route.query.sort) as SortOption) ||
40-
'downloads',
41-
)
44+
const rawSort = (Array.isArray(route.query.sort) ? route.query.sort[0] : route.query.sort) as
45+
| SortOption
46+
| 'downloads'
47+
| 'updated'
48+
| undefined
49+
const normalizedSort: SortOption =
50+
rawSort === 'downloads'
51+
? 'downloads-desc'
52+
: rawSort === 'updated'
53+
? 'updated-desc'
54+
: (rawSort ?? 'downloads-desc')
55+
56+
const sortOption = shallowRef<SortOption>(normalizedSort)
4257
4358
// Track if we've loaded all results (one-way flag, doesn't reset)
4459
// Initialize to true if URL already has filter/sort params
45-
const hasLoadedAll = shallowRef(
46-
Boolean(route.query.q) || (route.query.sort && route.query.sort !== 'downloads'),
47-
)
60+
const hasLoadedAll = shallowRef(Boolean(route.query.q) || normalizedSort !== 'downloads-desc')
4861
4962
// Update URL when filter/sort changes (debounced)
5063
const debouncedUpdateUrl = debounce((filter: string, sort: string) => {
@@ -53,7 +66,7 @@ const debouncedUpdateUrl = debounce((filter: string, sort: string) => {
5366
5467
watch([filterText, sortOption], ([filter, sort]) => {
5568
// Once user interacts with filter/sort, load all results
56-
if (!hasLoadedAll.value && (filter !== '' || sort !== 'downloads')) {
69+
if (!hasLoadedAll.value && (filter !== '' || sort !== 'downloads-desc')) {
5770
hasLoadedAll.value = true
5871
}
5972
debouncedUpdateUrl(filter, sort)
@@ -104,20 +117,30 @@ const filteredAndSortedPackages = computed(() => {
104117
105118
// Apply sort
106119
switch (sortOption.value) {
107-
case 'updated':
120+
case 'updated-desc':
108121
pkgs.sort((a, b) => {
109122
const dateA = a.package.date || ''
110123
const dateB = b.package.date || ''
111124
return dateB.localeCompare(dateA)
112125
})
113126
break
127+
case 'updated-asc':
128+
pkgs.sort((a, b) => {
129+
const dateA = a.package.date || ''
130+
const dateB = b.package.date || ''
131+
return dateA.localeCompare(dateB)
132+
})
133+
break
114134
case 'name-asc':
115135
pkgs.sort((a, b) => a.package.name.localeCompare(b.package.name))
116136
break
117137
case 'name-desc':
118138
pkgs.sort((a, b) => b.package.name.localeCompare(a.package.name))
119139
break
120-
case 'downloads':
140+
case 'downloads-asc':
141+
pkgs.sort((a, b) => (a.downloads?.weekly ?? 0) - (b.downloads?.weekly ?? 0))
142+
break
143+
case 'downloads-desc':
121144
default:
122145
pkgs.sort((a, b) => (b.downloads?.weekly ?? 0) - (a.downloads?.weekly ?? 0))
123146
break
@@ -158,7 +181,7 @@ function handlePageChange(page: number) {
158181
watch(username, () => {
159182
currentPage.value = 1
160183
filterText.value = ''
161-
sortOption.value = 'downloads'
184+
sortOption.value = 'downloads-desc'
162185
hasLoadedAll.value = false
163186
})
164187

i18n/locales/ar.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,10 @@
318318
"dependencies": "الاعتماديات"
319319
},
320320
"sort": {
321-
"downloads": "الأكثر تنزيلًا",
322-
"updated": "مُحدَّثة مؤخرًا",
321+
"downloads_desc": "الأكثر تنزيلًا",
322+
"downloads_asc": "الأقل تنزيلًا",
323+
"updated_desc": "مُحدَّثة مؤخرًا",
324+
"updated_asc": "الأقدم تحديثًا",
323325
"name_asc": "الاسم (A-Z)",
324326
"name_desc": "الاسم (Z-A)"
325327
}

i18n/locales/az.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,8 +337,10 @@
337337
"dependencies": "Asılılıqlar"
338338
},
339339
"sort": {
340-
"downloads": "Ən çox endirilən",
341-
"updated": "Son yenilənən",
340+
"downloads_desc": "Ən çox endirilən",
341+
"downloads_asc": "Ən az endirilən",
342+
"updated_desc": "Son yenilənən",
343+
"updated_asc": "Ən əvvəl yenilənən",
342344
"name_asc": "Ad (A-Z)",
343345
"name_desc": "Ad (Z-A)"
344346
}

i18n/locales/de-DE.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -347,8 +347,10 @@
347347
"dependencies": "Abhängigkeiten"
348348
},
349349
"sort": {
350-
"downloads": "Meiste Downloads",
351-
"updated": "Zuletzt aktualisiert",
350+
"downloads_desc": "Meiste Downloads",
351+
"downloads_asc": "Wenigste Downloads",
352+
"updated_desc": "Zuletzt aktualisiert",
353+
"updated_asc": "Am wenigsten kürzlich aktualisiert",
352354
"name_asc": "Name (A-Z)",
353355
"name_desc": "Name (Z-A)"
354356
}

i18n/locales/en.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,10 @@
355355
"dependencies": "Dependencies"
356356
},
357357
"sort": {
358-
"downloads": "Most downloaded",
359-
"updated": "Recently updated",
358+
"downloads_desc": "Most downloaded",
359+
"downloads_asc": "Least downloaded",
360+
"updated_desc": "Recently updated",
361+
"updated_asc": "Least recently updated",
360362
"name_asc": "Name (A-Z)",
361363
"name_desc": "Name (Z-A)"
362364
}

i18n/locales/es.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,10 @@
333333
"get_started": "Empezar"
334334
},
335335
"sort": {
336-
"downloads": "Más descargados",
337-
"updated": "Recientemente actualizados",
336+
"downloads_desc": "Más descargados",
337+
"downloads_asc": "Menos descargados",
338+
"updated_desc": "Recientemente actualizados",
339+
"updated_asc": "Menos recientemente actualizados",
338340
"name_asc": "Nombre (A-Z)",
339341
"name_desc": "Nombre (Z-A)"
340342
},

i18n/locales/fr-FR.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,10 @@
335335
"get_started": "Commencer"
336336
},
337337
"sort": {
338-
"downloads": "Plus téléchargés",
339-
"updated": "Récemment mis à jour",
338+
"downloads_desc": "Plus téléchargés",
339+
"downloads_asc": "Moins téléchargés",
340+
"updated_desc": "Récemment mis à jour",
341+
"updated_asc": "Les moins récemment mis à jour",
340342
"name_asc": "Nom (A-Z)",
341343
"name_desc": "Nom (Z-A)"
342344
},

i18n/locales/hu-HU.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,10 @@
335335
"dependencies": "Függőségek"
336336
},
337337
"sort": {
338-
"downloads": "Legtöbbször letöltött",
339-
"updated": "Legfrissebb",
338+
"downloads_desc": "Legtöbbször letöltött",
339+
"downloads_asc": "Legkevesebbet letöltött",
340+
"updated_desc": "Legfrissebb",
341+
"updated_asc": "Legrégebben frissített",
340342
"name_asc": "Név (A-Z)",
341343
"name_desc": "Név (Z-A)"
342344
}

i18n/locales/it-IT.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,10 @@
323323
"dependencies": "Dipendenze"
324324
},
325325
"sort": {
326-
"downloads": "Più scaricati",
327-
"updated": "Aggiornati di recente",
326+
"downloads_desc": "Più scaricati",
327+
"downloads_asc": "Meno scaricati",
328+
"updated_desc": "Aggiornati di recente",
329+
"updated_asc": "Aggiornati meno di recente",
328330
"name_asc": "Nome (A-Z)",
329331
"name_desc": "Nome (Z-A)"
330332
}

0 commit comments

Comments
 (0)