mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-04 19:21:51 +00:00
5b9824c379
Co-authored-by: Pablo F.G <pablo.fernandez@prowler.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
115 lines
3.7 KiB
TypeScript
115 lines
3.7 KiB
TypeScript
import { useSearchParams } from "next/navigation";
|
|
|
|
import { isScanEntity } from "@/lib/helper-filters";
|
|
import {
|
|
FILTER_FIELD,
|
|
FilterEntity,
|
|
FilterParam,
|
|
ProviderEntity,
|
|
ProviderType,
|
|
ScanEntity,
|
|
} from "@/types";
|
|
|
|
interface UseRelatedFiltersProps {
|
|
providerIds?: string[];
|
|
providerUIDs?: string[];
|
|
providerDetails: { [key: string]: FilterEntity }[];
|
|
completedScanIds?: string[];
|
|
scanDetails?: { [key: string]: ScanEntity }[];
|
|
enableScanRelation?: boolean;
|
|
providerFilterType?:
|
|
| typeof FILTER_FIELD.PROVIDER
|
|
| typeof FILTER_FIELD.PROVIDER_UID;
|
|
}
|
|
|
|
/**
|
|
* Derives available providers and scans based on the current URL filters.
|
|
*
|
|
* Pure computation — no effects, no state, no navigation. The returned
|
|
* lists update automatically when searchParams change because the component
|
|
* re-renders with new searchParams from Next.js.
|
|
*
|
|
* Cascading filter cleanup is handled atomically by composed filter controls
|
|
* such as ProviderAccountSelectors. This avoids the production bug where
|
|
* router.push() calls inside useEffect would silently abort pending
|
|
* navigations.
|
|
*/
|
|
export const useRelatedFilters = ({
|
|
providerIds = [],
|
|
providerUIDs = [],
|
|
providerDetails,
|
|
completedScanIds = [],
|
|
scanDetails = [],
|
|
enableScanRelation = false,
|
|
providerFilterType = FILTER_FIELD.PROVIDER,
|
|
}: UseRelatedFiltersProps) => {
|
|
const searchParams = useSearchParams();
|
|
|
|
const providers = providerIds.length > 0 ? providerIds : providerUIDs;
|
|
|
|
const providerParam = searchParams.get(
|
|
`filter[${providerFilterType}]` satisfies FilterParam,
|
|
);
|
|
const providerTypeParam = searchParams.get(
|
|
`filter[${FILTER_FIELD.PROVIDER_TYPE}]` satisfies FilterParam,
|
|
);
|
|
|
|
const currentProviders = providerParam ? providerParam.split(",") : [];
|
|
const currentProviderTypes = providerTypeParam
|
|
? (providerTypeParam.split(",") as ProviderType[])
|
|
: [];
|
|
|
|
const getProviderType = (providerKey: string): ProviderType | null => {
|
|
const providerDetail = providerDetails.find(
|
|
(detail) => Object.keys(detail)[0] === providerKey,
|
|
);
|
|
if (!providerDetail) return null;
|
|
|
|
const entity = providerDetail[providerKey];
|
|
if (!isScanEntity(entity as ScanEntity)) {
|
|
return (entity as ProviderEntity).provider;
|
|
}
|
|
return null;
|
|
};
|
|
|
|
// Derive available providers filtered by selected provider types
|
|
const availableProviders =
|
|
currentProviderTypes.length > 0
|
|
? providers.filter((key) => {
|
|
const providerType = getProviderType(key);
|
|
return providerType && currentProviderTypes.includes(providerType);
|
|
})
|
|
: providers;
|
|
|
|
// Derive available scans filtered by selected providers and provider types
|
|
const availableScans = enableScanRelation
|
|
? currentProviders.length > 0 || currentProviderTypes.length > 0
|
|
? completedScanIds.filter((scanId) => {
|
|
const scanDetail = scanDetails.find(
|
|
(detail) => Object.keys(detail)[0] === scanId,
|
|
);
|
|
if (!scanDetail) return false;
|
|
|
|
const scanProviderId = scanDetail[scanId]?.providerInfo?.uid ?? null;
|
|
const scanProviderType =
|
|
(scanDetail[scanId]?.providerInfo?.provider as ProviderType) ??
|
|
null;
|
|
|
|
return (
|
|
(currentProviders.length === 0 ||
|
|
(scanProviderId && currentProviders.includes(scanProviderId))) &&
|
|
(currentProviderTypes.length === 0 ||
|
|
(scanProviderType &&
|
|
currentProviderTypes.includes(scanProviderType)))
|
|
);
|
|
})
|
|
: completedScanIds
|
|
: completedScanIds;
|
|
|
|
return {
|
|
availableProviderIds: providerIds.length > 0 ? availableProviders : [],
|
|
availableProviderUIDs: providerUIDs.length > 0 ? availableProviders : [],
|
|
availableScans,
|
|
};
|
|
};
|