src/app/pages/people-profile/people-profile.component.ts
Page component for displaying people profiles
| changeDetection | ChangeDetectionStrategy.OnPush |
| selector | cns-people-profile |
| imports |
HraCommonModule
ChipsModule
ContactInfoComponent
FooterComponent
MarkdownComponent
MatSidenav
MatSidenavContainer
MatSidenavContent
PageSectionComponent
TableOfContentsLayoutComponent
TableOfContentsLayoutHeaderComponent
|
| templateUrl | ./people-profile.component.html |
| styleUrl | ./people-profile.component.scss |
Properties |
|
Inputs |
| data | |
Type : PeopleItem
|
|
| Required : true | |
|
Profile data from route resolver |
|
| Protected Readonly isMobile |
Type : unknown
|
Default value : watchBreakpoint(Breakpoints.Mobile)
|
|
Whether the current screen size matches mobile breakpoint |
| Protected Readonly primaryRole |
Type : unknown
|
Default value : computed(() => this.data().roles?.[0])
|
|
Primary role computed from profile data |
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
import { MatSidenav, MatSidenavContainer, MatSidenavContent } from '@angular/material/sidenav';
import { Breakpoints, watchBreakpoint } from '@hra-ui/cdk/breakpoints';
import { HraCommonModule } from '@hra-ui/common';
import { BreadcrumbItem } from '@hra-ui/design-system/buttons/breadcrumbs';
import { ChipsModule } from '@hra-ui/design-system/chips';
import { MarkdownComponent } from '@hra-ui/design-system/content-templates/markdown';
import { PageSectionComponent } from '@hra-ui/design-system/content-templates/page-section';
import {
TableOfContentsLayoutComponent,
TableOfContentsLayoutHeaderComponent,
} from '@hra-ui/design-system/layouts/table-of-contents';
import { FooterComponent } from '../../components/footer/footer.component';
import { PeopleItem } from '../../schemas/people.schema';
import { getRefinedRoleTypeLabel, refineRoleType } from '../../utils/refined-roles';
import { ContactInfoComponent } from './contact-info/contact-info.component';
/** Profile section data */
interface ProfileSection {
/** Section title/tagline */
tagline: string;
/** Section anchor id */
anchor: string;
/** Section content in markdown */
content: string;
}
/**
* Page component for displaying people profiles
*/
@Component({
selector: 'cns-people-profile',
imports: [
HraCommonModule,
ChipsModule,
ContactInfoComponent,
FooterComponent,
MarkdownComponent,
MatSidenav,
MatSidenavContainer,
MatSidenavContent,
PageSectionComponent,
TableOfContentsLayoutComponent,
TableOfContentsLayoutHeaderComponent,
],
templateUrl: './people-profile.component.html',
styleUrl: './people-profile.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PeopleProfileComponent {
/**
* Profile data from route resolver
*/
readonly data = input.required<PeopleItem>();
/** Whether the current screen size matches mobile breakpoint */
protected readonly isMobile = watchBreakpoint(Breakpoints.Mobile);
/** Breadcrumbs computed for navigation */
protected readonly breadcrumbs = computed((): BreadcrumbItem[] => [
{ name: 'Home', route: '/' },
{ name: 'People', route: '/people' },
{ name: this.data().name },
]);
/** Primary role computed from profile data */
protected readonly primaryRole = computed(() => this.data().roles?.[0]);
/** Whether contact info is available for display */
protected readonly hasContactInfo = computed(() => {
if (this.data().image) {
return true;
}
const role = this.primaryRole();
if (!role || role.type !== 'member') {
return false;
}
const { email, fax, office, phone } = role;
return !!(email || fax || office || phone);
});
/** Role tags computed for display */
protected readonly tags = computed(() => {
const role = this.primaryRole();
if (!role) {
return [];
}
const tags: string[] = [];
if (role.type === 'member') {
if (role.title) {
tags.push(role.title);
}
}
tags.push(getRefinedRoleTypeLabel(refineRoleType(role)));
return tags;
});
/** Profile sections computed from role data */
protected readonly sections = computed<ProfileSection[]>(() => {
const role = this.primaryRole();
if (!role) {
return [];
}
const sections: ProfileSection[] = [];
if (role.type === 'member') {
if (role.education) {
sections.push({
tagline: 'Education',
anchor: 'education',
content: role.education,
});
}
if (role.background) {
sections.push({
tagline: 'Background',
anchor: 'background',
content: role.background,
});
}
if (role.interests) {
sections.push({
tagline: 'Interests',
anchor: 'interests',
content: role.interests,
});
}
}
return sections;
});
}
<mat-sidenav-container class="container">
<mat-sidenav class="sidenav" role="complementary" mode="side" [opened]="hasContactInfo() && !isMobile()">
<cns-contact-info [image]="data().image" [role]="primaryRole()" />
</mat-sidenav>
<mat-sidenav-content class="content">
<hra-table-of-contents-layout class="layout-container">
<hra-table-of-contents-layout-header>
<hra-page-section
class="section"
[tagline]="data().name"
[level]="1"
[breadcrumbs]="breadcrumbs()"
[tags]="tags()"
>
@if (hasContactInfo() && isMobile()) {
<cns-contact-info [image]="data().image" [role]="primaryRole()" />
}
</hra-page-section>
</hra-table-of-contents-layout-header>
@for (section of sections(); track section.anchor) {
<hra-page-section class="section" [tagline]="section.tagline" [level]="2" [anchor]="section.anchor">
<hra-markdown [data]="section.content" />
</hra-page-section>
}
</hra-table-of-contents-layout>
<div class="spacer"></div>
<cns-footer />
</mat-sidenav-content>
</mat-sidenav-container>