Asymmetrik/ngx-starter

View on GitHub
src/app/core/messages/view-all-messages/view-all-messages.component.ts

Summary

Maintainability
A
0 mins
Test Coverage
F
51%
import { DOCUMENT, LowerCasePipe, NgClass } from '@angular/common';
import {
    Component,
    DestroyRef,
    HostListener,
    OnInit,
    inject,
    signal,
    viewChild
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

import { WINDOW } from '@ng-web-apis/common';

import { PagingOptions, SearchInputComponent, SortDirection } from '../../../common';
import { AgoDatePipe } from '../../../common/pipes';
import { SystemAlertComponent } from '../../../common/system-alert';
import { Message, MessageType } from '../message.model';
import { MessageService } from '../message.service';

@Component({
    selector: 'app-view-all-messages',
    templateUrl: './view-all-messages.component.html',
    styleUrls: ['./view-all-messages.component.scss'],
    standalone: true,
    imports: [SystemAlertComponent, SearchInputComponent, NgClass, LowerCasePipe, AgoDatePipe]
})
export class ViewAllMessagesComponent implements OnInit {
    readonly #destroyRef = inject(DestroyRef);
    readonly #messagesService = inject(MessageService);
    readonly #window = inject(WINDOW);
    readonly #document = inject(DOCUMENT);

    #pageNumber = 0;
    #loadMore = true;

    readonly searchInput = viewChild.required(SearchInputComponent);

    readonly newMessages = signal(false);
    readonly messages = signal<Message[]>([]);

    readonly messageType = MessageType;

    search = '';

    ngOnInit() {
        this.loadMessages(this.#pageNumber);
        this.#messagesService.messageReceived
            .pipe(takeUntilDestroyed(this.#destroyRef))
            .subscribe((message) => {
                this.newMessages.set(true);
            });
    }

    @HostListener('window:scroll')
    onScroll() {
        // If at the bottom of the page, load more messages
        if (
            this.#window.innerHeight + this.#window.scrollY >= this.#document.body.offsetHeight &&
            this.#loadMore
        ) {
            this.#loadMore = false; // Set to false temporarily to avoid multiple loads
            this.#pageNumber++;
            this.loadMessages(this.#pageNumber);
        }
    }

    loadMessages(page: number) {
        this.#messagesService
            .search(
                new PagingOptions(page, 20, 0, 0, 'created', SortDirection.desc),
                {},
                this.search
            )
            .pipe(takeUntilDestroyed(this.#destroyRef))
            .subscribe((result) => {
                if (page === 0) {
                    this.messages.set(result.elements);
                } else {
                    this.messages.update((messages) => [...messages, ...result.elements]);
                }
                if (this.messages.length < result.totalSize) {
                    this.#loadMore = true;
                }
            });
    }

    loadNewMessages() {
        this.newMessages.set(false);
        this.search = '';
        this.searchInput().clearSearch();
        this.#pageNumber = 0;
        this.loadMessages(this.#pageNumber);
    }

    onSearch(search: string) {
        this.search = search;
        this.#pageNumber = 0;
        this.loadMessages(this.#pageNumber);
    }
}