fixing and styleing
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<button mat-icon-button (click)="goBack()">
|
||||
<mat-icon>arrow_back</mat-icon>
|
||||
</button>
|
||||
<span class="toolbar-title">Items List</span>
|
||||
<span class="toolbar-title">{{ subcategoryName() || 'Items' }}</span>
|
||||
<span class="toolbar-spacer"></span>
|
||||
<button mat-mini-fab color="accent" (click)="addItem()">
|
||||
<mat-icon>add</mat-icon>
|
||||
@@ -133,4 +133,6 @@
|
||||
<p>No items found</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div #scrollSentinel class="scroll-sentinel"></div>
|
||||
</div>
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
font-size: 1.25rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.toolbar-spacer {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.filters-bar {
|
||||
@@ -267,3 +271,8 @@
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-sentinel {
|
||||
height: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, OnInit, signal, HostListener } from '@angular/core';
|
||||
import { Component, OnInit, AfterViewInit, OnDestroy, signal, ViewChild, ElementRef } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
@@ -39,14 +39,18 @@ import { ConfirmDialogComponent } from '../../components/confirm-dialog/confirm-
|
||||
templateUrl: './items-list.component.html',
|
||||
styleUrls: ['./items-list.component.scss']
|
||||
})
|
||||
export class ItemsListComponent implements OnInit {
|
||||
export class ItemsListComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
items = signal<Item[]>([]);
|
||||
loading = signal(false);
|
||||
hasMore = signal(true);
|
||||
hasMore = signal(false);
|
||||
page = signal(1);
|
||||
searchQuery = signal('');
|
||||
visibilityFilter = signal<boolean | undefined>(undefined);
|
||||
searchQuery = '';
|
||||
visibilityFilter: boolean | undefined = undefined;
|
||||
selectedItems = signal<Set<string>>(new Set());
|
||||
subcategoryName = signal<string>('');
|
||||
|
||||
@ViewChild('scrollSentinel') scrollSentinel!: ElementRef;
|
||||
private intersectionObserver?: IntersectionObserver;
|
||||
|
||||
subcategoryId = signal<string>('');
|
||||
projectId = signal<string>('');
|
||||
@@ -68,14 +72,17 @@ export class ItemsListComponent implements OnInit {
|
||||
|
||||
this.route.params.subscribe(params => {
|
||||
this.subcategoryId.set(params['subcategoryId']);
|
||||
this.page.set(1);
|
||||
this.items.set([]);
|
||||
this.selectedItems.set(new Set());
|
||||
this.subcategoryName.set('');
|
||||
this.loadSubcategoryName();
|
||||
this.loadItems();
|
||||
});
|
||||
}
|
||||
|
||||
loadItems(append = false) {
|
||||
if (this.loading() || (!append && this.items().length > 0)) {
|
||||
return;
|
||||
}
|
||||
if (this.loading()) return;
|
||||
|
||||
this.loading.set(true);
|
||||
const currentPage = append ? this.page() + 1 : 1;
|
||||
@@ -84,9 +91,9 @@ export class ItemsListComponent implements OnInit {
|
||||
this.subcategoryId(),
|
||||
currentPage,
|
||||
20,
|
||||
this.searchQuery() || undefined,
|
||||
this.searchQuery || undefined,
|
||||
{
|
||||
visible: this.visibilityFilter(),
|
||||
visible: this.visibilityFilter,
|
||||
tags: []
|
||||
}
|
||||
).subscribe({
|
||||
@@ -108,16 +115,31 @@ export class ItemsListComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('window:scroll', [])
|
||||
onScroll() {
|
||||
const scrollPosition = window.pageYOffset + window.innerHeight;
|
||||
const documentHeight = document.documentElement.scrollHeight;
|
||||
|
||||
if (scrollPosition >= documentHeight - 200 && this.hasMore() && !this.loading()) {
|
||||
this.loadItems(true);
|
||||
ngAfterViewInit() {
|
||||
this.intersectionObserver = new IntersectionObserver(
|
||||
entries => {
|
||||
if (entries[0].isIntersecting && this.hasMore() && !this.loading()) {
|
||||
this.loadItems(true);
|
||||
}
|
||||
},
|
||||
{ rootMargin: '200px', threshold: 0 }
|
||||
);
|
||||
if (this.scrollSentinel?.nativeElement) {
|
||||
this.intersectionObserver.observe(this.scrollSentinel.nativeElement);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.intersectionObserver?.disconnect();
|
||||
}
|
||||
|
||||
loadSubcategoryName() {
|
||||
this.apiService.getSubcategory(this.subcategoryId()).subscribe({
|
||||
next: (sub) => this.subcategoryName.set(sub.name),
|
||||
error: () => {}
|
||||
});
|
||||
}
|
||||
|
||||
onSearch() {
|
||||
this.page.set(1);
|
||||
this.items.set([]);
|
||||
@@ -205,6 +227,8 @@ export class ItemsListComponent implements OnInit {
|
||||
this.apiService.createItem(subcategoryId, result).subscribe({
|
||||
next: () => {
|
||||
this.snackBar.open('Item created successfully', 'Close', { duration: 3000 });
|
||||
this.page.set(1);
|
||||
this.items.set([]);
|
||||
this.loadItems();
|
||||
},
|
||||
error: (err) => {
|
||||
@@ -234,6 +258,8 @@ export class ItemsListComponent implements OnInit {
|
||||
this.apiService.deleteItem(item.id).subscribe({
|
||||
next: () => {
|
||||
this.snackBar.open('Item deleted successfully', 'Close', { duration: 3000 });
|
||||
this.page.set(1);
|
||||
this.items.set([]);
|
||||
this.loadItems();
|
||||
},
|
||||
error: (err) => {
|
||||
|
||||
Reference in New Issue
Block a user