@@ -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