diff --git a/apps/nextjs/src/app/[locale]/manage/apps/page.tsx b/apps/nextjs/src/app/[locale]/manage/apps/page.tsx index 2029fbafa..8dd13774b 100644 --- a/apps/nextjs/src/app/[locale]/manage/apps/page.tsx +++ b/apps/nextjs/src/app/[locale]/manage/apps/page.tsx @@ -1,7 +1,7 @@ import Link from "next/link"; import { redirect } from "next/navigation"; import { ActionIcon, ActionIconGroup, Anchor, Avatar, Card, Group, Stack, Text, Title } from "@mantine/core"; -import { IconApps, IconPencil } from "@tabler/icons-react"; +import { IconBox, IconPencil } from "@tabler/icons-react"; import type { RouterOutputs } from "@homarr/api"; import { api } from "@homarr/api/server"; @@ -12,6 +12,7 @@ import { getI18n, getScopedI18n } from "@homarr/translation/server"; import { ManageContainer } from "~/components/manage/manage-container"; import { MobileAffixButton } from "~/components/manage/mobile-affix-button"; import { DynamicBreadcrumb } from "~/components/navigation/dynamic-breadcrumb"; +import { NoResults } from "~/components/no-results"; import { AppDeleteButton } from "./_app-delete-button"; export default async function AppsPage() { @@ -113,16 +114,14 @@ const AppNoResults = async () => { const session = await auth(); return ( - - - - - {t("app.page.list.noResults.title")} - - {session?.user.permissions.includes("app-create") && ( - {t("app.page.list.noResults.action")} - )} - - + ); }; diff --git a/apps/nextjs/src/app/[locale]/manage/integrations/page.tsx b/apps/nextjs/src/app/[locale]/manage/integrations/page.tsx index a600effed..853630698 100644 --- a/apps/nextjs/src/app/[locale]/manage/integrations/page.tsx +++ b/apps/nextjs/src/app/[locale]/manage/integrations/page.tsx @@ -27,7 +27,7 @@ import { Text, Title, } from "@mantine/core"; -import { IconChevronDown, IconChevronUp, IconPencil } from "@tabler/icons-react"; +import { IconChevronDown, IconChevronUp, IconPencil, IconPlugX } from "@tabler/icons-react"; import type { RouterOutputs } from "@homarr/api"; import { api } from "@homarr/api/server"; @@ -40,6 +40,7 @@ import { CountBadge, IntegrationAvatar } from "@homarr/ui"; import { ManageContainer } from "~/components/manage/manage-container"; import { DynamicBreadcrumb } from "~/components/navigation/dynamic-breadcrumb"; +import { NoResults } from "~/components/no-results"; import { ActiveTabAccordion } from "../../../../components/active-tab-accordion"; import { DeleteIntegrationActionButton } from "./_integration-buttons"; import { IntegrationCreateDropdownContent } from "./new/_integration-new-dropdown"; @@ -120,7 +121,7 @@ const IntegrationList = async ({ integrations, activeTab }: IntegrationListProps const hasFullAccess = session?.user.permissions.includes("integration-full-all") ?? false; if (integrations.length === 0) { - return
{t("page.list.empty")}
; + return ; } const grouppedIntegrations = integrations.reduce( diff --git a/apps/nextjs/src/app/[locale]/manage/search-engines/page.tsx b/apps/nextjs/src/app/[locale]/manage/search-engines/page.tsx index 8f66abbf1..5d56fe17c 100644 --- a/apps/nextjs/src/app/[locale]/manage/search-engines/page.tsx +++ b/apps/nextjs/src/app/[locale]/manage/search-engines/page.tsx @@ -13,6 +13,7 @@ import { z } from "@homarr/validation"; import { ManageContainer } from "~/components/manage/manage-container"; import { MobileAffixButton } from "~/components/manage/mobile-affix-button"; import { DynamicBreadcrumb } from "~/components/navigation/dynamic-breadcrumb"; +import { NoResults } from "~/components/no-results"; import { SearchEngineDeleteButton } from "./_search-engine-delete-button"; const searchParamsSchema = z.object({ @@ -142,16 +143,14 @@ const SearchEngineNoResults = async () => { const session = await auth(); return ( - - - - - {t("search.engine.page.list.noResults.title")} - - {session?.user.permissions.includes("search-engine-create") && ( - {t("search.engine.page.list.noResults.action")} - )} - - + ); }; diff --git a/apps/nextjs/src/components/no-results.tsx b/apps/nextjs/src/components/no-results.tsx new file mode 100644 index 000000000..c25724297 --- /dev/null +++ b/apps/nextjs/src/components/no-results.tsx @@ -0,0 +1,26 @@ +import { Anchor, Card, Stack, Text } from "@mantine/core"; +import type { TablerIcon } from "@tabler/icons-react"; + +interface NoResultsProps { + icon: TablerIcon; + title: string; + action?: { + label: string; + href: string; + hidden?: boolean; + }; +} + +export const NoResults = ({ icon: Icon, title, action }: NoResultsProps) => { + return ( + + + + + {title} + + {!action?.hidden && {action?.label}} + + + ); +}; diff --git a/packages/translation/src/lang/en.json b/packages/translation/src/lang/en.json index 7b8655ed1..cac220e9f 100644 --- a/packages/translation/src/lang/en.json +++ b/packages/translation/src/lang/en.json @@ -388,7 +388,7 @@ "list": { "title": "Apps", "noResults": { - "title": "There aren't any apps", + "title": "There are no apps yet", "action": "Create your first app" } }, @@ -456,7 +456,9 @@ "list": { "title": "Integrations", "search": "Search integrations", - "empty": "No integrations found" + "noResults": { + "title": "There are no integrations yet" + } }, "create": { "title": "New {name} integration", @@ -2676,7 +2678,7 @@ "list": { "title": "Search engines", "noResults": { - "title": "There aren't any search engines", + "title": "There are no search engines yet", "action": "Create your first search engine" }, "interactive": "Interactive, uses an integration"