feat: articles pagination

This commit is contained in:
Florian Sylvain committed 2026-10-11 19:14:37 +02:00
1 parent a2d224240c
commit 73f4b539fe
45 files changed
+3528 -317

No files matched your search

@@ -8,16 +8,51 @@ vi.mock('@/composables/useApi', () => ({
import { useArticles } from '@/composables/useArticles'
const envelope = {
items: [],
total: 0,
page: 1,
size: 25,
counts: { all: 0, online: 0, draft: 0 },
}
describe('useArticles', () => {
beforeEach(() => {
request.mockReset()
request.mockResolvedValue(envelope)
})
it('asks the API for html bodies when listing articles', async () => {
request.mockResolvedValue([])
it('asks the API for html bodies with explicit paging when listing articles', async () => {
await useArticles().listArticles({ page: 1, size: 25 })
await useArticles().listArticles()
expect(request).toHaveBeenCalledWith('/v1/article/?format=html&page=1&size=25')
})
expect(request).toHaveBeenCalledWith('/v1/article/?format=html')
it('sends the search text and the status when they are set', async () => {
await useArticles().listArticles({ page: 2, size: 50, q: 'plaster', status: 'draft' })
expect(request).toHaveBeenCalledWith(
'/v1/article/?format=html&page=2&size=50&q=plaster&status=draft',
)
})
it('sends the sort when it is set', async () => {
await useArticles().listArticles({ page: 1, size: 25, sort: 'title:asc' })
expect(request).toHaveBeenCalledWith(
'/v1/article/?format=html&page=1&size=25&sort=title%3Aasc',
)
})
it('omits an empty search and an empty status', async () => {
await useArticles().listArticles({ page: 3, size: 5, q: '', status: '' })
expect(request).toHaveBeenCalledWith('/v1/article/?format=html&page=3&size=5')
})
it('returns the envelope untouched', async () => {
const result = await useArticles().listArticles({ page: 1, size: 25 })
expect(result).toEqual(envelope)
})
})
+41 -2
View File
@@ -1,4 +1,5 @@
import { useApi } from '@/composables/useApi'
import type { ArticleStatus } from '@/lib/articleListQuery'
export interface Article {
id: number
@@ -9,11 +10,49 @@ export interface Article {
updated_at: string
}
export type { ArticleStatus }
export interface ArticleCounts {
all: number
online: number
draft: number
}
export interface ArticlePage {
items: Article[]
total: number
page: number
size: number
counts: ArticleCounts
}
export interface ListArticlesParams {
page: number
size: number
q?: string
status?: ArticleStatus | ''
sort?: string
}
export function useArticles() {
const { request } = useApi()
function listArticles(): Promise<Article[]> {
return request<Article[]>('/v1/article/?format=html')
function listArticles(params: ListArticlesParams): Promise<ArticlePage> {
const query = new URLSearchParams({
format: 'html',
page: String(params.page),
size: String(params.size),
})
if (params.q) {
query.set('q', params.q)
}
if (params.status) {
query.set('status', params.status)
}
if (params.sort) {
query.set('sort', params.sort)
}
return request<ArticlePage>(`/v1/article/?${query.toString()}`)
}
return { listArticles }