File

src/app/pages/current-team/current-team.component.ts

Description

Page component for displaying current team members

Metadata

Index

Properties
Inputs

Constructor

constructor()

Initializes the component and store with route data

  • Sets people data from route resolver

Inputs

data
Type : PeopleData
Required :  true

Team members data from route resolver

Properties

Protected Readonly placeholderImage
Type : string
Default value : '/assets/placeholder-images/placeholder.png'

Gender neutral placeholder image for members without pictures

Protected Readonly sidebarStore
Type : unknown
Default value : inject(SidebarStore)

Sidebar store for managing sidebar state

Protected Readonly store
Type : unknown
Default value : inject(CurrentTeamStore)

Store for managing team member state and filters

import { ChangeDetectionStrategy, Component, effect, inject, input, viewChild } from '@angular/core';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { MatSidenav, MatSidenavModule } from '@angular/material/sidenav';
import { HraCommonModule } from '@hra-ui/common';
import { LinkDirective } from '@hra-ui/common/router-ext';
import { ButtonsModule } from '@hra-ui/design-system/buttons';
import { ProfileCardComponent } from '@hra-ui/design-system/cards/profile-card';
import { SectionLinkComponent } from '@hra-ui/design-system/content-templates/section-link';
import { FilterMenuComponent } from '@hra-ui/design-system/filter-menu';
import { GalleryGridComponent, GalleryGridItemDirective } from '@hra-ui/design-system/gallery-grid';
import { IconsModule } from '@hra-ui/design-system/icons';
import { NoResultsIndicatorComponent } from '@hra-ui/design-system/indicators/no-results-indicator';
import { ScrollingModule } from '@hra-ui/design-system/scrolling';
import { SearchFilterComponent } from '@hra-ui/design-system/search-filter';
import { FooterComponent } from '../../components/footer/footer.component';
import { PeopleData } from '../../schemas/people.schema';
import { SidebarStore } from '../../state/sidebar/sidebar.store';
import { CurrentTeamStore } from './state/current-team.store';

/**
 * Page component for displaying current team members
 */
@Component({
  selector: 'cns-current-team',
  imports: [
    HraCommonModule,
    ButtonsModule,
    FilterMenuComponent,
    FooterComponent,
    GalleryGridComponent,
    GalleryGridItemDirective,
    IconsModule,
    LinkDirective,
    MatButtonToggleModule,
    MatFormFieldModule,
    MatSelectModule,
    MatSidenavModule,
    NoResultsIndicatorComponent,
    ProfileCardComponent,
    ScrollingModule,
    SearchFilterComponent,
    SectionLinkComponent,
  ],
  templateUrl: './current-team.component.html',
  styleUrl: './current-team.component.scss',
  providers: [CurrentTeamStore],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CurrentTeamComponent {
  /**
   * Team members data from route resolver
   */
  readonly data = input.required<PeopleData>();

  /** Store for managing team member state and filters */
  protected readonly store = inject(CurrentTeamStore);

  /** Sidebar store for managing sidebar state */
  protected readonly sidebarStore = inject(SidebarStore);

  /** Gender neutral placeholder image for members without pictures */
  protected readonly placeholderImage = '/assets/placeholder-images/placeholder.png';

  /** Reference to the sidebar component */
  private readonly sidebar = viewChild.required(MatSidenav);

  /**
   * Initializes the component and store with route data
   * - Sets people data from route resolver
   */
  constructor() {
    this.store.setPeople(this.data);

    effect((onCleanup) => {
      this.sidebarStore.setSidebar(this.sidebar());
      onCleanup(() => this.sidebarStore.clearSidebar());
    });
  }
}
<mat-sidenav-container class="container">
  <mat-sidenav
    class="sidebar"
    aria-label="Filter team members"
    [mode]="sidebarStore.mode()"
    [opened]="sidebarStore.isOpen()"
    [disableClose]="sidebarStore.mode() === 'side'"
    (closedStart)="sidebarStore.close()"
  >
    <hra-filter-menu
      class="filters"
      tagline="People at the Cyberinfrastructure for Network Science Center"
      [filters]="store.filters()"
      (filtersChange)="store.setFilters($event)"
    >
      <mat-button-toggle-group
        hraButtonToggleSize="medium"
        class="team-toggle"
        aria-label="Select team"
        [value]="store.team()"
        (valueChange)="store.setTeam($event)"
      >
        <mat-button-toggle value="current">Current team</mat-button-toggle>
        <mat-button-toggle value="past">Former team</mat-button-toggle>
      </mat-button-toggle-group>

      <mat-form-field class="sort-by" subscriptSizing="dynamic">
        <mat-icon class="select-icon" matPrefix>sort</mat-icon>
        <mat-label>Sort by</mat-label>
        <mat-select [value]="store.sortBy()" (valueChange)="store.setSortBy($event)">
          @if (store.team() === 'current') {
            <mat-option value="hierarchical">Hierarchical</mat-option>
          }
          <mat-option value="lastNameAsc">Last name (ascending A-Z)</mat-option>
          <mat-option value="lastNameDesc">Last name (descending Z-A)</mat-option>
          <mat-option value="endYearNewest">End year (new to old)</mat-option>
          <mat-option value="startYearOldest">Start year (old to new)</mat-option>
        </mat-select>
      </mat-form-field>

      <mat-form-field class="group-by" subscriptSizing="dynamic">
        <mat-icon class="select-icon" matPrefix>category</mat-icon>
        <mat-label>Group by</mat-label>
        <mat-select [value]="store.groupBy()" (valueChange)="store.setGroupBy($event)">
          <mat-option [value]="null">None</mat-option>
          <mat-option value="role">Role</mat-option>
          <mat-option value="startYear">Start year</mat-option>
          <mat-option value="endYear">End year</mat-option>
        </mat-select>
      </mat-form-field>
    </hra-filter-menu>
  </mat-sidenav>

  <mat-sidenav-content role="main">
    <ng-scrollbar>
      <div class="content">
        <div class="search-bar">
          <hra-search-filter
            label="Search"
            separator="/"
            [totalCount]="store.numFilteredByTeam()"
            [viewingCount]="store.numFilteredPeople()"
            [search]="store.search() ?? ''"
            (searchChange)="store.setSearch($event)"
          />
        </div>

        <div class="profile-list">
          @if (store.numFilteredPeople() === 0) {
            <hra-no-results-indicator (clearFilters)="store.resetFilters()" />
          } @else {
            @for (group of store.sortedGroupedPeople(); track group.label) {
              <section class="section">
                @if (group.label) {
                  <h3 hra-section-link class="title" [underlined]="true">{{ group.label }}</h3>
                }
                <hra-gallery-grid class="gallery" [dataSource]="group.people">
                  <hra-profile-card
                    *hraGalleryGridItem="let person"
                    [pictureUrl]="person.image ? person.image : placeholderImage"
                    [name]="person.name"
                    [description]="store.getMemberTitle(person)"
                    [centerContent]="true"
                  >
                    @if (store.team() === 'current') {
                      <a
                        mat-button
                        hraHyperlink
                        class="learn-more"
                        [hraLink]="`/people/${person.slug}`"
                        [attr.aria-label]="`Learn more about ${person.name}`"
                      >
                        Learn more
                        <mat-icon iconPositionEnd>arrow_right_alt</mat-icon>
                      </a>
                    }
                  </hra-profile-card>
                </hra-gallery-grid>
              </section>
            }
          }
        </div>

        <cns-footer class="footer" />
      </div>
    </ng-scrollbar>
  </mat-sidenav-content>
</mat-sidenav-container>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""