/** * Copyright since 2025 Mifos Initiative * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { inject } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivateFn, Router } from '@angular/router'; import { Observable, of } from 'rxjs'; import { catchError, map } from 'rxjs/operators'; import { ClientsService } from '../clients.service'; import { familyAllowed, nomineeAllowed } from './client-rules'; /** * Walk up the route snapshot tree until we find a `clientId` path param. The * family-members / nominees routes are nested two levels under the client * shell, so simple `route.params['clientId']` returns undefined. */ function findClientId(route: ActivatedRouteSnapshot): string | null { let cur: ActivatedRouteSnapshot | null = route; while (cur) { const id = cur.params?.['clientId']; if (id) return id; cur = cur.parent; } return null; } /** * Build a guard that redirects to the client's General tab when the client * isn't eligible for the section. Resolves the client lazily so we don't * couple the guard to any specific parent resolver. */ function makeEligibilityGuard( predicate: (legalFormId: number | null | undefined, constitutionLabel?: string | null) => boolean ): CanActivateFn { return (route) => { const router = inject(Router); const clientsService = inject(ClientsService); const clientId = findClientId(route); // No clientId in the URL — let the framework's own missing-param handling kick in. if (!clientId) return true; return clientsService.getClientData(clientId).pipe( map((client: any) => { const legalFormId = client?.legalForm?.id; const constitutionLabel = client?.clientNonPersonDetails?.constitution?.name || ''; if (predicate(legalFormId, constitutionLabel)) return true; return router.createUrlTree([ '/clients', clientId, 'general' ]); }), // If the client lookup fails, fail open and let downstream handle it // rather than redirecting users into an infinite loop on a stale URL. catchError(() => of(true)) ) as Observable>; }; } export const familyAllowedGuard: CanActivateFn = makeEligibilityGuard(familyAllowed); export const nomineeAllowedGuard: CanActivateFn = makeEligibilityGuard(nomineeAllowed);