Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FE - implement screen when there is nothing to show #155

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions client/src/components/icons/menu-pointer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { SVGProps } from "react";

export const MenuPointer = (props: SVGProps<SVGSVGElement>) => {
return (
<svg
width="80"
height="80"
viewBox="0 0 80 80"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<g opacity="0.5">
<path
d="M13.333 40H66.6663"
stroke="#94A3B8"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M13.333 20H66.6663"
stroke="#94A3B8"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M13.75 60H40"
stroke="#94A3B8"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M65.4167 50.9791L62.5 53.75"
stroke="#94A3B8"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M52.4372 56.6667L48.208 55.5"
stroke="#94A3B8"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M53.7503 62.5L50.9795 65.4167"
stroke="#94A3B8"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M55.5 48.2084L56.6667 52.4375"
stroke="#94A3B8"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M58.1788 59.1312C58.1223 58.998 58.1068 58.851 58.1344 58.7089C58.162 58.5668 58.2315 58.4363 58.3338 58.3339C58.4361 58.2316 58.5667 58.1622 58.7088 58.1346C58.8508 58.1069 58.9979 58.1224 59.1311 58.179L75.1728 64.7415C75.3156 64.8 75.4361 64.9024 75.517 65.0338C75.5979 65.1652 75.635 65.3189 75.623 65.4727C75.611 65.6266 75.5505 65.7727 75.4502 65.89C75.3499 66.0072 75.215 66.0897 75.0649 66.1254L68.7226 67.6435C68.4608 67.7061 68.2214 67.8399 68.0309 68.0301C67.8404 68.2203 67.7063 68.4595 67.6434 68.7212L66.1268 75.065C66.0914 75.2156 66.0091 75.3511 65.8916 75.4519C65.7742 75.5526 65.6277 75.6134 65.4735 75.6254C65.3192 75.6374 65.1652 75.6 65.0335 75.5187C64.9019 75.4374 64.7996 75.3163 64.7413 75.1729L58.1788 59.1312Z"
stroke="#94A3B8"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
</svg>
);
};

export default MenuPointer;
14 changes: 11 additions & 3 deletions client/src/containers/no-data/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,26 @@ import NoDataIcon from "@/components/icons/no-data";

interface NoDataProps {
className?: HTMLDivElement["className"] | undefined;
/**
* Overrides default icon
*/
icon?: React.ReactNode;
/**
* Overrides default description
*/
description?: string;
}

const NoData: FC<NoDataProps> = ({ className }) => {
const NoData: FC<NoDataProps> = ({ className, icon, description }) => {
return (
<div
className={cn(
"flex h-full flex-col items-center justify-center gap-4 rounded-2xl bg-disabled-background/5 p-8 text-xs text-disabled-foreground",
className,
)}
>
<NoDataIcon />
<p>No data available for this item.</p>
{icon || <NoDataIcon />}
<p>{description || "No data available for this item."}</p>
</div>
);
};
Expand Down
10 changes: 9 additions & 1 deletion client/src/containers/sandbox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { FC, useEffect } from "react";
import useFilters from "@/hooks/use-filters";
import useSandboxWidget from "@/hooks/use-sandbox-widget";

import NoData from "@/containers/no-data";
import Widget from "@/containers/widget";
import CreateWidgetMenu from "@/containers/widget/create-widget";

import MenuPointer from "@/components/icons/menu-pointer";
import { Card } from "@/components/ui/card";

const Sandbox: FC = () => {
Expand All @@ -24,7 +26,7 @@ const Sandbox: FC = () => {

return (
<Card className="p-0">
{widget && (
{widget ? (
<Widget
breakdown={breakdown || undefined}
indicator={widget.indicator}
Expand All @@ -41,6 +43,12 @@ const Sandbox: FC = () => {
className="col-span-1 last:odd:col-span-2"
config={{ menu: { className: "flex flex-col py-4" } }}
/>
) : (
<NoData
icon={<MenuPointer />}
description="Select an indicator to visualize its data."
className="m-6 gap-6"
/>
)}
</Card>
);
Expand Down
21 changes: 18 additions & 3 deletions client/tests/no-data.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,27 @@ vi.mock("@/components/icons/no-data", () => ({
}));

describe("NoData", () => {
const defaultDescription = "No data available for this item.";
it("renders the correct content", () => {
render(<NoData />);

expect(screen.getByTestId("no-data-icon")).toBeInTheDocument();
expect(
screen.getByText("No data available for this item."),
).toBeInTheDocument();
expect(screen.getByText(defaultDescription)).toBeInTheDocument();
});

it("renders with custom description", () => {
const customDescription = "Custom description";
render(<NoData description={customDescription} />);

expect(screen.getByText(customDescription)).toBeInTheDocument();
expect(screen.queryByText(defaultDescription)).not.toBeInTheDocument();
});

it("renders with custom icon", () => {
const CustomIcon = () => <div data-testid="custom-icon">Custom Icon</div>;
render(<NoData icon={<CustomIcon />} />);

expect(screen.getByTestId("custom-icon")).toBeInTheDocument();
expect(screen.queryByTestId("no-data-icon")).not.toBeInTheDocument();
});
});
Loading