mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-05-06 08:47:18 +00:00
d23c2f3b53
Co-authored-by: Pablo F.G <pablo.fernandez@prowler.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
118 lines
4.0 KiB
TypeScript
118 lines
4.0 KiB
TypeScript
import { Suspense } from "react";
|
|
|
|
import { ProvidersAccountsView } from "@/components/providers";
|
|
import { SkeletonTableProviders } from "@/components/providers/table";
|
|
import { Skeleton } from "@/components/shadcn/skeleton/skeleton";
|
|
import { ContentLayout } from "@/components/ui";
|
|
import { FilterTransitionWrapper } from "@/contexts";
|
|
import { SearchParamsProps } from "@/types";
|
|
|
|
import { ProviderGroupsContent } from "./provider-groups-content";
|
|
import { ProviderPageTabs } from "./provider-page-tabs";
|
|
import { getProviderTab } from "./provider-page-tabs.shared";
|
|
import { loadProvidersAccountsViewData } from "./providers-page.utils";
|
|
|
|
export default async function Providers({
|
|
searchParams,
|
|
}: {
|
|
searchParams: Promise<SearchParamsProps>;
|
|
}) {
|
|
const resolvedSearchParams = await searchParams;
|
|
const activeTab = getProviderTab(resolvedSearchParams.tab);
|
|
|
|
// Exclude `tab` from the Suspense key so switching tabs doesn't re-suspend
|
|
const { tab: _, ...paramsWithoutTab } = resolvedSearchParams || {};
|
|
const searchParamsKey = JSON.stringify(paramsWithoutTab);
|
|
|
|
return (
|
|
<ContentLayout title="Providers" icon="lucide:cloud-cog">
|
|
<FilterTransitionWrapper>
|
|
<ProviderPageTabs
|
|
activeTab={activeTab}
|
|
providersContent={
|
|
<Suspense
|
|
key={`providers-${searchParamsKey}`}
|
|
fallback={<ProvidersTableFallback />}
|
|
>
|
|
<ProvidersTabContent searchParams={resolvedSearchParams} />
|
|
</Suspense>
|
|
}
|
|
providerGroupsContent={
|
|
<Suspense
|
|
key={`groups-${searchParamsKey}`}
|
|
fallback={<ProviderGroupsFallback />}
|
|
>
|
|
<ProviderGroupsContent searchParams={resolvedSearchParams} />
|
|
</Suspense>
|
|
}
|
|
/>
|
|
</FilterTransitionWrapper>
|
|
</ContentLayout>
|
|
);
|
|
}
|
|
|
|
const ProvidersTableFallback = () => {
|
|
return (
|
|
<div className="flex flex-col gap-6">
|
|
<div className="flex flex-wrap items-center gap-4">
|
|
{/* ProviderTypeSelector */}
|
|
<Skeleton className="h-[52px] min-w-[200px] flex-1 rounded-lg md:max-w-[280px]" />
|
|
{/* Organizations filter */}
|
|
<Skeleton className="h-[52px] max-w-[240px] min-w-[180px] flex-1 rounded-lg" />
|
|
{/* Provider Groups filter */}
|
|
<Skeleton className="h-[52px] max-w-[240px] min-w-[180px] flex-1 rounded-lg" />
|
|
{/* Status filter */}
|
|
<Skeleton className="h-[52px] max-w-[240px] min-w-[180px] flex-1 rounded-lg" />
|
|
{/* Action buttons */}
|
|
<div className="ml-auto flex flex-wrap gap-4">
|
|
<Skeleton className="h-9 w-[160px] rounded-md" />
|
|
<Skeleton className="h-9 w-[120px] rounded-md" />
|
|
</div>
|
|
</div>
|
|
<SkeletonTableProviders />
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const ProviderGroupsFallback = () => {
|
|
return (
|
|
<div className="grid min-h-[50vh] grid-cols-1 items-start gap-8 md:grid-cols-12">
|
|
<div className="col-span-1 md:col-span-4">
|
|
<div className="flex flex-col gap-4">
|
|
<Skeleton className="h-7 w-48 rounded" />
|
|
<Skeleton className="h-4 w-64 rounded" />
|
|
<Skeleton className="h-10 w-full rounded-md" />
|
|
<Skeleton className="h-10 w-full rounded-md" />
|
|
<Skeleton className="h-10 w-full rounded-md" />
|
|
<Skeleton className="h-10 w-32 rounded-md" />
|
|
</div>
|
|
</div>
|
|
<div className="col-span-1 md:col-span-1" />
|
|
<div className="col-span-1 md:col-span-6">
|
|
<SkeletonTableProviders />
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const ProvidersTabContent = async ({
|
|
searchParams,
|
|
}: {
|
|
searchParams: SearchParamsProps;
|
|
}) => {
|
|
const providersView = await loadProvidersAccountsViewData({
|
|
searchParams,
|
|
isCloud: process.env.NEXT_PUBLIC_IS_CLOUD_ENV === "true",
|
|
});
|
|
|
|
return (
|
|
<ProvidersAccountsView
|
|
isCloud={process.env.NEXT_PUBLIC_IS_CLOUD_ENV === "true"}
|
|
filters={providersView.filters}
|
|
providers={providersView.providers}
|
|
metadata={providersView.metadata}
|
|
rows={providersView.rows}
|
|
/>
|
|
);
|
|
};
|