11import type { PrismaClient } from '@prisma/client' ;
22
3- import { isIsoDate } from '../utils/date-utils' ;
3+ import {
4+ LIST_ARTICLES_PER_PAGE ,
5+ TILES_ARTICLES_PER_BLOG ,
6+ TILES_BLOGS_PER_PAGE ,
7+ } from '../constants' ;
48
5- import { cursorToText , textToCursor } from './cursor-encoding' ;
69import { HTTPNotFound } from './errors' ;
710
8- export const TILES_BLOGS_PER_PAGE = 4 ;
9- export const TILES_ARTICLES_PER_BLOG = 5 ;
10- export const LIST_ARTICLES_PER_PAGE = 20 ;
11-
12- function last < T extends readonly R [ ] , R > ( arr : readonly [ R , ...T ] ) : R ;
13- function last < T > ( arr : readonly T [ ] ) : T | undefined ;
14- function last < T > ( arr : readonly T [ ] ) : T | undefined {
15- return arr [ arr . length - 1 ] ;
16- }
17-
18- export const getArticlesForGrid = async ( prisma : PrismaClient , cursor ?: string ) => {
19- const date = cursor && cursorToText ( cursor ) ;
20-
21- if ( date && ! isIsoDate ( date ) ) {
22- throw new HTTPNotFound ( ) ;
23- }
24-
25- const where = date
26- ? {
27- lastArticlePublishedAt : {
28- lt : date ,
29- not : null ,
30- } ,
31- }
32- : { } ;
33-
11+ export const getArticlesForGrid = async ( prisma : PrismaClient , page : number ) => {
12+ const pageNumber = reversePageNumber ( page , await getLastBlogPage ( prisma ) ) ;
3413 const blogs = await prisma . blog . findMany ( {
35- where : { ...where , isPublic : true } ,
14+ where : { isPublic : true } ,
15+ skip : pageNumber * TILES_BLOGS_PER_PAGE ,
3616 take : TILES_BLOGS_PER_PAGE ,
3717 orderBy : {
3818 lastArticlePublishedAt : 'desc' ,
@@ -46,52 +26,34 @@ export const getArticlesForGrid = async (prisma: PrismaClient, cursor?: string)
4626 } ,
4727 } ,
4828 } ) ;
29+ if ( blogs . length === 0 ) throw new HTTPNotFound ( ) ;
4930
50- const lastBlog = last ( blogs ) ;
5131 return {
5232 data : blogs ,
53- nextCursor :
54- lastBlog ?. lastArticlePublishedAt &&
55- textToCursor ( lastBlog ?. lastArticlePublishedAt . toISOString ( ) ) ,
5633 } ;
5734} ;
5835
59- export const getArticlesPaginationForGrid = async ( prisma : PrismaClient ) => {
60- const blogs = ( await prisma . blog . findMany ( {
61- where : { isPublic : true , lastArticlePublishedAt : { not : null } } ,
62- orderBy : {
63- lastArticlePublishedAt : 'desc' ,
64- } ,
65- select : {
66- lastArticlePublishedAt : true ,
67- } ,
68- } ) ) as ReadonlyArray < { readonly lastArticlePublishedAt : Date } > ;
69-
70- const cursors = blogs . flatMap ( ( blog , index ) => {
71- if ( index % TILES_BLOGS_PER_PAGE === TILES_BLOGS_PER_PAGE - 1 ) {
72- return [ textToCursor ( blog . lastArticlePublishedAt . toISOString ( ) ) ] ;
73- }
74- return [ ] ;
36+ export const getLastArticlePage = async ( prisma : PrismaClient ) => {
37+ const articlesCount = await prisma . article . count ( {
38+ where : { blog : { isPublic : true } } ,
7539 } ) ;
76- return cursors ;
40+ return Math . ceil ( articlesCount / LIST_ARTICLES_PER_PAGE ) ;
7741} ;
7842
79- export const getArticlesForList = async ( prisma : PrismaClient , cursor ?: string ) => {
80- const date = cursor && cursorToText ( cursor ) ;
81-
82- if ( date && ! isIsoDate ( date ) ) {
83- throw new HTTPNotFound ( ) ;
84- }
85-
86- const where = date
87- ? {
88- publishedAt : {
89- lt : date ,
90- } ,
91- }
92- : { } ;
43+ export const getLastBlogPage = async ( prisma : PrismaClient ) => {
44+ const blogCount = await prisma . blog . count ( {
45+ where : { isPublic : true , lastArticlePublishedAt : { not : null } } ,
46+ } ) ;
47+ return Math . ceil ( blogCount / TILES_BLOGS_PER_PAGE ) ;
48+ } ;
49+ const reversePageNumber = ( page : number , lastPage : number ) : number => {
50+ return lastPage - page ;
51+ } ;
52+ export const getArticlesForList = async ( prisma : PrismaClient , page : number ) => {
53+ const pageNumber = reversePageNumber ( page , await getLastArticlePage ( prisma ) ) ;
9354 const articles = await prisma . article . findMany ( {
94- where : { ...where , blog : { isPublic : true } } ,
55+ skip : pageNumber * LIST_ARTICLES_PER_PAGE ,
56+ where : { blog : { isPublic : true } } ,
9557 take : LIST_ARTICLES_PER_PAGE ,
9658 orderBy : {
9759 publishedAt : 'desc' ,
@@ -100,36 +62,12 @@ export const getArticlesForList = async (prisma: PrismaClient, cursor?: string)
10062 blog : true ,
10163 } ,
10264 } ) ;
103-
104- const lastArticle = last ( articles ) ;
65+ if ( articles . length === 0 ) throw new HTTPNotFound ( ) ;
10566 return {
10667 data : articles ,
107- nextCursor : lastArticle ?. publishedAt && textToCursor ( lastArticle ?. publishedAt . toISOString ( ) ) ,
10868 } ;
10969} ;
11070
111- export const getArticlesPaginationForList = async ( prisma : PrismaClient ) => {
112- const articles = await prisma . article . findMany ( {
113- where : {
114- blog : { isPublic : true } ,
115- } ,
116- orderBy : {
117- publishedAt : 'desc' ,
118- } ,
119- select : {
120- publishedAt : true ,
121- } ,
122- } ) ;
123-
124- const cursors = articles . flatMap ( ( article , index ) => {
125- if ( index % LIST_ARTICLES_PER_PAGE === LIST_ARTICLES_PER_PAGE - 1 ) {
126- return [ textToCursor ( article . publishedAt . toISOString ( ) ) ] ;
127- }
128- return [ ] ;
129- } ) ;
130- return cursors ;
131- } ;
132-
13371export const getArticlesSlugs = async ( prisma : PrismaClient , limit ?: number ) => {
13472 const articles = await prisma . article . findMany ( {
13573 where : {
0 commit comments