- Expand en.ts/zh.ts with extensive translation keys for all modules - Localize Peers table, peer detail page, peer action cells - Localize Access Control table, modal, action cells - Localize Groups table, action cells, main page - Add common helpers (GroupsRow, NoPeersGettingStarted) translations Continuation of the localization effort.
111 lines
3.2 KiB
TypeScript
111 lines
3.2 KiB
TypeScript
import Button from "@components/Button";
|
|
import Paragraph from "@components/Paragraph";
|
|
import { cn } from "@utils/helpers";
|
|
import { FilterX } from "lucide-react";
|
|
import { useTranslations } from 'next-intl';
|
|
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
|
import React, { useCallback } from "react";
|
|
import Skeleton from "react-loading-skeleton";
|
|
import SquareIcon from "@components/SquareIcon";
|
|
|
|
type Props = {
|
|
icon?: React.ReactNode;
|
|
title?: string;
|
|
description?: string;
|
|
children?: React.ReactNode;
|
|
className?: string;
|
|
hasFiltersApplied?: boolean;
|
|
onResetFilters?: () => void;
|
|
contentClassName?: string;
|
|
};
|
|
|
|
export default function NoResults({
|
|
icon,
|
|
title,
|
|
description,
|
|
children,
|
|
className,
|
|
hasFiltersApplied = false,
|
|
onResetFilters,
|
|
contentClassName,
|
|
}: Props) {
|
|
const t = useTranslations('table');
|
|
const router = useRouter();
|
|
const pathname = usePathname();
|
|
const searchParams = useSearchParams();
|
|
|
|
const defaultTitle = title || t('noResults');
|
|
const defaultDescription = description || t('noResultsDescription');
|
|
|
|
const handleResetClick = useCallback(() => {
|
|
if (onResetFilters) {
|
|
onResetFilters();
|
|
|
|
const params = new URLSearchParams();
|
|
|
|
const page_size = searchParams.get("page_size");
|
|
|
|
params.set("page", "1");
|
|
|
|
if (page_size) {
|
|
params.set("page_size", page_size);
|
|
}
|
|
|
|
const newUrl = `${pathname}?${params.toString()}`;
|
|
router.push(newUrl);
|
|
}
|
|
}, [onResetFilters, router, pathname, searchParams]);
|
|
|
|
return (
|
|
<div className={cn("relative overflow-hidden", className)}>
|
|
<div
|
|
className={
|
|
"absolute z-20 bg-gradient-to-b dark:to-nb-gray-950 dark:from-nb-gray-950/50 w-full h-full overflow-hidden top-0"
|
|
}
|
|
></div>
|
|
<div
|
|
className={
|
|
"absolute w-full h-full left-0 top-0 z-10 px-5 overflow-hidden py-4"
|
|
}
|
|
>
|
|
<div className={"flex flex-col gap-2"}>
|
|
<Skeleton className={"w-full"} height={70} duration={4} />
|
|
<Skeleton className={"w-full"} height={70} duration={4} />
|
|
<Skeleton className={"w-full"} height={70} duration={4} />
|
|
<Skeleton className={"w-full"} height={70} duration={4} />
|
|
<Skeleton className={"w-full"} height={70} duration={4} />
|
|
</div>
|
|
</div>
|
|
<div
|
|
className={cn("max-w-md mx-auto relative z-20 py-6", contentClassName)}
|
|
>
|
|
<div className={"flex items-center justify-center mb-6"}>
|
|
<SquareIcon
|
|
icon={icon ? icon : <FilterX size={24} />}
|
|
color={"gray"}
|
|
size={"large"}
|
|
/>
|
|
</div>
|
|
|
|
<div className={"text-center"}>
|
|
<h1 className={"text-2xl font-medium max-w-lg mx-auto"}>{defaultTitle}</h1>
|
|
<Paragraph className={"justify-center my-2 !text-nb-gray-400"}>
|
|
{defaultDescription}
|
|
</Paragraph>
|
|
{hasFiltersApplied && onResetFilters && (
|
|
<Button
|
|
onClick={handleResetClick}
|
|
variant="secondary"
|
|
className="mt-4"
|
|
>
|
|
<FilterX size={16} />
|
|
{t('resetFilters')}
|
|
</Button>
|
|
)}
|
|
{children}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|