@@ -3,7 +3,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
33import { DatePipe } from '@angular/common' ;
44import { ActivatedRoute , RouterLink } from '@angular/router' ;
55import { Subject , catchError , distinctUntilChanged , map , of , startWith , switchMap , tap } from 'rxjs' ;
6- import { LucideAngularModule , BookOpen , AlertCircle } from 'lucide-angular' ;
6+ import { LucideAngularModule , BookOpen , AlertCircle , ChevronLeft , ChevronRight } from 'lucide-angular' ;
77import { ApiService } from '../../../core/services/api' ;
88import { SeoService } from '../../../core/services/seo.service' ;
99import { BlogPostSnippet } from '../../../core/models/blog.models' ;
@@ -13,7 +13,24 @@ import { stripMarkdown } from '../../../core/utils/markdown.utils';
1313type PageState = 'loading' | 'loaded' | 'error' ;
1414type Loaded = { page : PaginatedResult < BlogPostSnippet > } | { failure : unknown } ;
1515
16+ type PageLink = { kind : 'page' ; page : number } | { kind : 'gap' ; key : string } ;
17+
1618const PAGE_SIZE = 10 ;
19+ const SIBLINGS = 1 ;
20+
21+ function pageWindow ( current : number , total : number ) : PageLink [ ] {
22+ let start = Math . max ( 2 , current - SIBLINGS ) ;
23+ let end = Math . min ( total - 1 , current + SIBLINGS ) ;
24+ if ( start === 3 ) start = 2 ;
25+ if ( end === total - 2 ) end = total - 1 ;
26+
27+ const links : PageLink [ ] = [ { kind : 'page' , page : 1 } ] ;
28+ if ( start > 2 ) links . push ( { kind : 'gap' , key : 'gap-start' } ) ;
29+ for ( let page = start ; page <= end ; page ++ ) links . push ( { kind : 'page' , page } ) ;
30+ if ( end < total - 1 ) links . push ( { kind : 'gap' , key : 'gap-end' } ) ;
31+ if ( total > 1 ) links . push ( { kind : 'page' , page : total } ) ;
32+ return links ;
33+ }
1734
1835@Component ( {
1936 selector : 'app-blog-list' ,
@@ -29,14 +46,16 @@ export class BlogListComponent {
2946
3047 readonly BookOpenIcon = BookOpen ;
3148 readonly AlertIcon = AlertCircle ;
49+ readonly PrevIcon = ChevronLeft ;
50+ readonly NextIcon = ChevronRight ;
3251 readonly skeletonRows = [ 1 , 2 , 3 ] ;
3352 readonly stripMarkdown = stripMarkdown ;
3453
3554 posts = signal < BlogPostSnippet [ ] > ( [ ] ) ;
3655 state = signal < PageState > ( 'loading' ) ;
3756 currentPage = signal ( 1 ) ;
3857 totalPages = signal ( 0 ) ;
39- pages = computed ( ( ) => Array . from ( { length : this . totalPages ( ) } , ( _ , index ) => index + 1 ) ) ;
58+ pages = computed ( ( ) => pageWindow ( this . currentPage ( ) , this . totalPages ( ) ) ) ;
4059
4160 private reload$ = new Subject < void > ( ) ;
4261
0 commit comments