src/app/features/attendance/analysis/grouped-child-attendance/grouped-child-attendance.component.ts

Description

Lists all activities of the given child and displays a tab with detailed analysis for each.

Example

Metadata

Relationships

Used by

No results matching.

Depends on

Index

Properties
Methods
Inputs

Inputs

entity
Type : Entity

Methods

onActivityChange
onActivityChange(selectedArchivedActivity: Entity)
Parameters :
Name Type Optional
selectedArchivedActivity Entity No
Returns : void

Properties

activities
Type : unknown
Default value : computed(() => this.activitiesResource.value()?.active ?? [])
Protected activitiesResource
Type : unknown
Default value : resource({ params: () => ({ entity: this.entity() }), loader: async ({ params: { entity } }) => { if (!entity) return { active: [], archived: [] }; try { const allActivities = await this.attendanceService.getActivitiesForParticipant( entity.getId(), ); return { active: allActivities.filter((a) => !a.inactive), archived: allActivities.filter((a) => a.inactive), }; } catch (error) { Logging.warn( "Could not load grouped child attendance activities", error, ); return { active: [], archived: [] }; } }, })
archivedActivities
Type : unknown
Default value : computed( () => this.activitiesResource.value()?.archived ?? [], )
selectedActivity
Type : unknown
Default value : linkedSignal<Entity | undefined>(() => { this.entity(); return undefined; })
import {
  Component,
  ViewEncapsulation,
  inject,
  ChangeDetectionStrategy,
  computed,
  input,
  linkedSignal,
  resource,
} from "@angular/core";
import { Entity } from "#src/app/core/entity/model/entity";
import { AttendanceService } from "../../attendance.service";
import { DynamicComponent } from "#src/app/core/config/dynamic-components/dynamic-component.decorator";
import { MatProgressBarModule } from "@angular/material/progress-bar";
import { MatTabsModule } from "@angular/material/tabs";
import { TabStateModule } from "#src/app/utils/tab-state/tab-state.module";
import { ActivityAttendanceSectionComponent } from "../activity-attendance-section/activity-attendance-section.component";
import { MatSelectModule } from "@angular/material/select";
import { Logging } from "#src/app/core/logging/logging.service";

/**
 * Lists all activities of the given child
 * and displays a tab with detailed analysis for each.
 */
@DynamicComponent("GroupedChildAttendance")
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: "app-grouped-child-attendance",
  templateUrl: "./grouped-child-attendance.component.html",
  styleUrls: ["./grouped-child-attendance.component.scss"],
  encapsulation: ViewEncapsulation.None,
  imports: [
    MatProgressBarModule,
    MatTabsModule,
    TabStateModule,
    ActivityAttendanceSectionComponent,
    MatSelectModule,
  ],
})
export class GroupedChildAttendanceComponent {
  private attendanceService = inject(AttendanceService);

  entity = input<Entity>();

  protected activitiesResource = resource({
    params: () => ({ entity: this.entity() }),
    loader: async ({ params: { entity } }) => {
      if (!entity) return { active: [], archived: [] };
      try {
        const allActivities =
          await this.attendanceService.getActivitiesForParticipant(
            entity.getId(),
          );
        return {
          active: allActivities.filter((a) => !a.inactive),
          archived: allActivities.filter((a) => a.inactive),
        };
      } catch (error) {
        Logging.warn(
          "Could not load grouped child attendance activities",
          error,
        );
        return { active: [], archived: [] };
      }
    },
  });

  activities = computed(() => this.activitiesResource.value()?.active ?? []);
  archivedActivities = computed(
    () => this.activitiesResource.value()?.archived ?? [],
  );

  selectedActivity = linkedSignal<Entity | undefined>(() => {
    this.entity();
    return undefined;
  });

  onActivityChange(selectedArchivedActivity: Entity) {
    this.selectedActivity.set(selectedArchivedActivity);
  }
}
@if (activitiesResource.isLoading()) {
  <div>
    <mat-progress-bar mode="indeterminate"></mat-progress-bar>
  </div>
}

<mat-tab-group
  appTabStateMemo
  tabIndexKey="activityTab"
  class="activity-tab-group"
>
  @for (activity of activities(); track activity) {
    <mat-tab [label]="activity.toString()">
      <app-activity-attendance-section
        [entity]="activity"
        [forChild]="entity()?.getId()"
      >
      </app-activity-attendance-section>
    </mat-tab>
  }

  @if (archivedActivities().length > 0) {
    <mat-tab i18n-label label="Previous Activities">
      <p i18n>
        This section displays historical activities that have been archived.
      </p>
      <mat-form-field>
        <mat-label i18n>Select activity</mat-label>
        <mat-select (selectionChange)="onActivityChange($event.value)">
          @for (
            archivedActivity of archivedActivities();
            track archivedActivity
          ) {
            <mat-option [value]="archivedActivity">
              {{ archivedActivity.toString() }}
            </mat-option>
          }
        </mat-select>
      </mat-form-field>
      @if (selectedActivity()) {
        <div>
          <app-activity-attendance-section
            [entity]="selectedActivity()"
            [forChild]="entity()?.getId()"
          >
          </app-activity-attendance-section>
        </div>
      }
    </mat-tab>
  }
</mat-tab-group>

./grouped-child-attendance.component.scss

.activity-tab-group .mat-mdc-tab-body-content {
  overflow: hidden;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""