Add contacts, reply/forward, pagination, HTML toggle, Docker Compose for VPS

Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
2026-11-05 01:28:24 +01:00
co-authored by Junie
parent 0339413d6e
commit a23a020138
14 changed files with 570 additions and 12 deletions
@@ -89,6 +89,31 @@ import { of } from 'rxjs';
</div>
}
</div>
<!-- Пагинация -->
@if (totalPages() > 1) {
<div class="glass-panel p-4 flex items-center justify-center gap-2">
<button (click)="goToPage(page() - 1)" [disabled]="page() === 0"
class="px-3 py-1 rounded-lg text-xs font-mono text-synth-cyan border border-synth-cyan/30 hover:bg-synth-cyan/10 disabled:opacity-30 disabled:cursor-not-allowed transition-all">
← Prev
</button>
@for (p of pageNumbers; track p) {
<button (click)="goToPage(p)"
[class.bg-synth-pink/20]="p === page()" [class.text-synth-pink]="p === page()"
[class.border-synth-pink]="p === page()"
class="px-3 py-1 rounded-lg text-xs font-mono text-slate-400 border border-synth-cyan/20 hover:bg-synth-cyan/10 hover:text-synth-cyan transition-all">
{{ p + 1 }}
</button>
}
<button (click)="goToPage(page() + 1)" [disabled]="page() >= totalPages() - 1"
class="px-3 py-1 rounded-lg text-xs font-mono text-synth-cyan border border-synth-cyan/30 hover:bg-synth-cyan/10 disabled:opacity-30 disabled:cursor-not-allowed transition-all">
Next →
</button>
<span class="text-xs font-mono text-slate-500 ml-2">
Page {{ page() + 1 }} of {{ totalPages() }}
</span>
</div>
}
</div>
`,
styles: ``
@@ -100,6 +125,9 @@ export default class InboxComponent {
folderName = signal<string>('INBOX');
searchQuery = '';
folderId = signal<number>(1);
page = signal<number>(0);
totalPages = signal<number>(1);
pageSize = 20;
constructor() {
// Подписываемся на изменения folderId в queryParams
@@ -130,16 +158,39 @@ export default class InboxComponent {
loadMessages(): void {
const currentFolderId = this.folderId();
const currentPage = this.page();
if (this.searchQuery.trim()) {
this.mailService.searchMessages(currentFolderId, this.searchQuery.trim()).subscribe({
next: (msgs) => this.messages.set(msgs),
error: () => console.error('Search failed')
});
} else {
this.mailService.getMessages(currentFolderId).subscribe({
next: (msgs) => this.messages.set(msgs),
this.mailService.getMessages(currentFolderId, currentPage, this.pageSize).subscribe({
next: (result) => {
this.messages.set(result.content);
this.totalPages.set(result.totalPages);
},
error: () => console.error('Failed to load messages')
});
}
}
goToPage(page: number): void {
if (page >= 0 && page < this.totalPages()) {
this.page.set(page);
this.loadMessages();
}
}
get pageNumbers(): number[] {
const pages: number[] = [];
const total = this.totalPages();
const current = this.page();
const start = Math.max(0, current - 2);
const end = Math.min(total - 1, current + 2);
for (let i = start; i <= end; i++) {
pages.push(i);
}
return pages;
}
}