Skip to content

Commit

Permalink
portalicious: registrations table component (#6104)
Browse files Browse the repository at this point in the history
AB#31335

Moving the registrations table into a separate component so that it can easily be re-used by the "do payment" flow
  • Loading branch information
aberonni authored Nov 14, 2024
1 parent 930cefd commit 2a103ee
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 173 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export class QueryTableComponent<TData extends { id: PropertyKey }, TContext> {
items = input.required<TData[]>();
isPending = input.required<boolean>();
columns = input.required<QueryTableColumn<TData>[]>();
localStorageKey = input.required<string>();
localStorageKey = input<string>();
contextMenuItems = input<MenuItem[]>();
globalFilterFields = input<(keyof TData & string)[]>();
expandableRowTemplate = input<Type<TableCellComponent<TData, TContext>>>();
Expand Down Expand Up @@ -244,7 +244,10 @@ export class QueryTableComponent<TData extends { id: PropertyKey }, TContext> {

clearAllFilters() {
this.table.clear();
localStorage.removeItem(this.localStorageKey());
const localStorageKey = this.localStorageKey();
if (localStorageKey) {
localStorage.removeItem(localStorageKey);
}
this.globalFilterVisible.set(false);
this.tableFilters.set({});
this.selectAll.set(false);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<app-query-table
#table
[items]="registrations()"
[isPending]="registrationsResponse.isPending()"
[columns]="columns()"
[localStorageKey]="localStorageKey()"
[serverSideFiltering]="true"
[serverSideTotalRecords]="totalRegistrations()"
(onUpdatePaginateQuery)="paginateQuery.set($event)"
[enableSelection]="true"
(onUpdateSelection)="tableSelection.set($event)"
[contextMenuItems]="contextMenuItems()"
(onUpdateContextMenuItem)="contextMenuRegistration.set($event)"
>
<div table-actions>
<ng-content select="[table-actions]"></ng-content>
</div>
</app-query-table>
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import {
ChangeDetectionStrategy,
Component,
computed,
inject,
input,
signal,
ViewChild,
} from '@angular/core';

import { injectQuery } from '@tanstack/angular-query-experimental';
import { MenuItem } from 'primeng/api';

import { RegistrationStatusEnum } from '@121-service/src/registration/enum/registration-status.enum';
import { PermissionEnum } from '@121-service/src/user/enum/permission.enum';

import { getChipDataByRegistrationStatus } from '~/components/colored-chip/colored-chip.helper';
import {
QueryTableColumn,
QueryTableColumnType,
QueryTableComponent,
QueryTableSelectionEvent,
} from '~/components/query-table/query-table.component';
import { RegistrationApiService } from '~/domains/registration/registration.api.service';
import {
REGISTRATION_STATUS_LABELS,
registrationLink,
} from '~/domains/registration/registration.helper';
import { Registration } from '~/domains/registration/registration.model';
import {
PaginateQuery,
PaginateQueryService,
} from '~/services/paginate-query.service';
import { ToastService } from '~/services/toast.service';

@Component({
selector: 'app-registrations-table',
standalone: true,
imports: [QueryTableComponent],
templateUrl: './registrations-table.component.html',
styles: ``,
providers: [ToastService],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RegistrationsTableComponent {
projectId = input.required<number>();
contextMenuItems = input<MenuItem[]>();
localStorageKey = input<string>();

private paginateQueryService = inject(PaginateQueryService);
private registrationApiService = inject(RegistrationApiService);
private toastService = inject(ToastService);

PermissionEnum = PermissionEnum;

@ViewChild('table')
private table: QueryTableComponent<Registration, never>;

protected RegistrationStatusEnum = RegistrationStatusEnum;
protected paginateQuery = signal<PaginateQuery | undefined>(undefined);
protected tableSelection = signal<QueryTableSelectionEvent<Registration>>([]);
public contextMenuRegistration = signal<Registration | undefined>(undefined);

protected registrationsResponse = injectQuery(
this.registrationApiService.getManyByQuery(
this.projectId,
this.paginateQuery,
),
);

protected registrations = computed(
() => this.registrationsResponse.data()?.data ?? [],
);
protected totalRegistrations = computed(
() => this.registrationsResponse.data()?.meta.totalItems ?? 0,
);

protected columns = computed<QueryTableColumn<Registration>[]>(() => [
{
field: 'personAffectedSequence',
fieldForSort: 'registrationProgramId',
header: $localize`PA #`,
getCellRouterLink: (registration) =>
registrationLink({
projectId: this.projectId(),
registrationId: registration.id,
}),
},
{
field: 'fullName',
header: $localize`:@@registration-full-name:Full Name`,
getCellRouterLink: (registration) =>
registrationLink({
projectId: this.projectId(),
registrationId: registration.id,
}),
},
{
field: 'registrationCreated',
fieldForFilter: 'registrationCreatedDate',
header: $localize`:@@registration-created:Registration created`,
type: QueryTableColumnType.DATE,
},
{
field: 'status',
header: $localize`:@@registration-status:Status`,
type: QueryTableColumnType.MULTISELECT,
options: Object.entries(REGISTRATION_STATUS_LABELS).map(
([value, label]) => ({
label,
value,
}),
),
getCellChipData: (registration) =>
getChipDataByRegistrationStatus(registration.status),
},
]);

public getActionData({
triggeredFromContextMenu = false,
}: {
triggeredFromContextMenu?: boolean;
} = {}) {
let selection = this.tableSelection();

if (Array.isArray(selection) && selection.length === 0) {
if (triggeredFromContextMenu) {
const contextMenuRegistration = this.contextMenuRegistration();
if (!contextMenuRegistration) {
this.toastService.showGenericError();
return;
}
selection = [contextMenuRegistration];
} else {
this.toastService.showToast({
severity: 'error',
detail: $localize`:@@no-registrations-selected:Select one or more registrations and try again.`,
});
return;
}
}

return this.paginateQueryService.selectionEventToActionData({
selection,
fieldForFilter: 'referenceId',
totalCount: this.totalRegistrations(),
currentPaginateQuery: this.paginateQuery(),
previewItemForSelectAll: this.registrations()[0],
});
}

public resetSelection() {
this.table.resetSelection();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ActivityTypeEnum } from '@121-service/src/activities/enum/activity-type.enum';
import { RegistrationStatusEnum } from '@121-service/src/registration/enum/registration-status.enum';

import { AppRoutes } from '~/app.routes';
import { ChipVariant } from '~/components/colored-chip/colored-chip.component';
import {
// TODO: AB#30525 should import this from 121-service
Expand Down Expand Up @@ -83,3 +84,19 @@ export const ACTIVITY_LOG_ITEM_TYPE_ICONS: Record<ActivityTypeEnum, string> = {
[ActivityTypeEnum.StatusChange]: 'pi pi-refresh',
[ActivityTypeEnum.Transaction]: 'pi pi-money-bill',
};

export function registrationLink({
projectId,
registrationId,
}: {
projectId: number;
registrationId: number;
}) {
return [
'/',
AppRoutes.project,
projectId,
AppRoutes.projectRegistrations,
registrationId,
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,22 @@
@if (canExport()) {
<app-export-registrations
[projectId]="projectId()"
[getActionData]="getActionData.bind(this)"
[getActionData]="
registrationsTable.getActionData.bind(registrationsTable)
"
/>
}
</div>
<p-card>
<app-query-table
#table
[items]="registrations()"
[isPending]="registrationsResponse.isPending()"
[columns]="columns()"
localStorageKey="project-registrations-table"
[serverSideFiltering]="true"
[serverSideTotalRecords]="totalRegistrations()"
(onUpdatePaginateQuery)="paginateQuery.set($event)"
[enableSelection]="true"
(onUpdateSelection)="tableSelection.set($event)"
<app-registrations-table
#registrationsTable
[projectId]="projectId()"
[localStorageKey]="'project-registrations-table-' + projectId()"
[contextMenuItems]="contextMenuItems()"
(onUpdateContextMenuItem)="contextMenuRegistration.set($event)"
>
<div table-actions>
<p-buttonGroup>
@if (
canChangeStatus(RegistrationStatusEnum.validated) &&
project.data()?.validation
) {
@if (canChangeStatus()(RegistrationStatusEnum.validated)) {
<p-button
label="Validate"
i18n-label
Expand All @@ -49,7 +40,7 @@
"
/>
}
@if (canChangeStatus(RegistrationStatusEnum.included)) {
@if (canChangeStatus()(RegistrationStatusEnum.included)) {
<p-button
label="Include"
i18n-label
Expand All @@ -61,7 +52,7 @@
"
/>
}
@if (canChangeStatus(RegistrationStatusEnum.declined)) {
@if (canChangeStatus()(RegistrationStatusEnum.declined)) {
<p-button
label="Decline"
i18n-label
Expand All @@ -73,7 +64,7 @@
"
/>
}
@if (canChangeStatus(RegistrationStatusEnum.paused)) {
@if (canChangeStatus()(RegistrationStatusEnum.paused)) {
<p-button
label="Pause"
i18n-label
Expand All @@ -93,7 +84,7 @@
(click)="sendMessage()"
/>
}
@if (canChangeStatus(RegistrationStatusEnum.deleted)) {
@if (canChangeStatus()(RegistrationStatusEnum.deleted)) {
<p-button
label="Delete"
i18n-label
Expand All @@ -105,7 +96,7 @@
}
</p-buttonGroup>
</div>
</app-query-table>
</app-registrations-table>
</p-card>
</app-page-layout>

Expand Down
Loading

0 comments on commit 2a103ee

Please sign in to comment.