feat(ui): add empty-state and expose addPlaylist event

Introduce explicit empty-state handling in RecentPlaylists:
- Replace previous direct rendering of an empty mat-list item with
  app-empty-state for two cases: a global "welcome" state when no
  playlists exist at all, and a "no-results" state when filters/search
  return nothing. This clarifies UX and provides a CTA for adding
  playlists in the welcome state.
- Change playlist data binding from playlists$ to playlistsData$ and
  adapt loops and accessors to data.playlists / data.totalCount.
- Keep existing global favorites item and playlist-item rendering.

Wire up addPlaylist event and components:
- Add addPlaylistClicked output to RecentPlaylists component and
  forward the event from the home component so the parent can open
  the add-playlist flow.
- Import EmptyStateComponent and PlaylistType types used by the new
  output.

Minor cleanup and imports:
- Reformat some imports and add tap to RxJS imports.
- Adjust template structure and placeholders for deferred loading.
This commit is contained in:
4gray committed 2025-12-06 21:44:25 +01:00
1 parent b82d47f6b6
commit aa2d5b9508
6 files changed
+68 -82

No files matched your search

@@ -1,4 +1,4 @@
import { Component, HostBinding, OnInit, effect, inject, input, output } from '@angular/core';
import { Component, HostBinding, OnInit, effect, inject, input, output, viewChild } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
@@ -13,18 +13,17 @@ import { TranslateModule } from '@ngx-translate/core';
import { DataService, SortBy, SortOrder, SortService } from 'services';
//import { shell } from 'electron';
import { selectActiveTypeFilters, setSelectedFilters } from 'm3u-state';
import { AddPlaylistMenuComponent, PlaylistType } from 'components';
import { HomeComponent } from '../../../home/home.component';
import { AboutDialogComponent } from '../about-dialog/about-dialog.component';
import {
AddPlaylistDialogComponent,
PlaylistType,
} from '../add-playlist/add-playlist-dialog.component';
import { AddPlaylistDialogComponent } from '../add-playlist/add-playlist-dialog.component';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss'],
imports: [
AddPlaylistMenuComponent,
FormsModule,
MatButtonModule,
MatCheckboxModule,
@@ -40,6 +39,7 @@ export class HeaderComponent implements OnInit {
@HostBinding('class.home-header') get isHomeHeader() {
return this.isHome;
}
private activatedRoute = inject(ActivatedRoute);
private dialog = inject(MatDialog);
private dataService = inject(DataService);
@@ -47,6 +47,7 @@ export class HeaderComponent implements OnInit {
private store = inject(Store);
private sortService = inject(SortService);
readonly addPlaylistMenuComponent = viewChild.required(AddPlaylistMenuComponent);
readonly isDesktop = !!window.electron;
readonly title = input.required<string>();
readonly subtitle = input.required<string>();