aboutsummaryrefslogtreecommitdiffstats
path: root/apps/web/components
diff options
context:
space:
mode:
authorMohamed Bassem <me@mbassem.com>2024-12-30 12:15:35 +0000
committerMohamed Bassem <me@mbassem.com>2024-12-30 12:15:35 +0000
commit5902664658a36e4afc81327eea9f8eef05561bcb (patch)
treeb72415e988efb5cd95e4a28634b0b53bf125b168 /apps/web/components
parent179f00b15525b024b6823088ef8fb94b7106b4f0 (diff)
downloadkarakeep-5902664658a36e4afc81327eea9f8eef05561bcb.tar.zst
refactor: Refactor sidebar into a shared component
Diffstat (limited to 'apps/web/components')
-rw-r--r--apps/web/components/admin/sidebar/items.tsx31
-rw-r--r--apps/web/components/dashboard/sidebar/ModileSidebar.tsx23
-rw-r--r--apps/web/components/dashboard/sidebar/Sidebar.tsx81
-rw-r--r--apps/web/components/settings/sidebar/ModileSidebar.tsx21
-rw-r--r--apps/web/components/settings/sidebar/Sidebar.tsx36
-rw-r--r--apps/web/components/settings/sidebar/items.tsx55
-rw-r--r--apps/web/components/shared/sidebar/MobileSidebar.tsx (renamed from apps/web/components/admin/sidebar/MobileSidebar.tsx)13
-rw-r--r--apps/web/components/shared/sidebar/Sidebar.tsx (renamed from apps/web/components/admin/sidebar/Sidebar.tsx)22
-rw-r--r--apps/web/components/shared/sidebar/SidebarLayout.tsx37
-rw-r--r--apps/web/components/shared/sidebar/TSidebarItem.ts5
10 files changed, 63 insertions, 261 deletions
diff --git a/apps/web/components/admin/sidebar/items.tsx b/apps/web/components/admin/sidebar/items.tsx
deleted file mode 100644
index 78dfee34..00000000
--- a/apps/web/components/admin/sidebar/items.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import { TFunction } from "i18next";
-import { Activity, ArrowLeft, Settings, Users } from "lucide-react";
-
-export const adminSidebarItems = (
- t: TFunction,
-): {
- name: string;
- icon: JSX.Element;
- path: string;
-}[] => [
- {
- name: t("settings.back_to_app"),
- icon: <ArrowLeft size={18} />,
- path: "/dashboard/bookmarks",
- },
- {
- name: t("admin.server_stats.server_stats"),
- icon: <Activity size={18} />,
- path: "/admin/overview",
- },
- {
- name: t("admin.users_list.users_list"),
- icon: <Users size={18} />,
- path: "/admin/users",
- },
- {
- name: t("common.actions"),
- icon: <Settings size={18} />,
- path: "/admin/actions",
- },
-];
diff --git a/apps/web/components/dashboard/sidebar/ModileSidebar.tsx b/apps/web/components/dashboard/sidebar/ModileSidebar.tsx
deleted file mode 100644
index 777877bf..00000000
--- a/apps/web/components/dashboard/sidebar/ModileSidebar.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import MobileSidebarItem from "@/components/shared/sidebar/ModileSidebarItem";
-import HoarderLogoIcon from "@/public/icons/logo-icon.svg";
-import { ClipboardList, Highlighter, Search, Tag } from "lucide-react";
-
-export default async function MobileSidebar() {
- return (
- <aside className="w-full">
- <ul className="flex justify-between space-x-2 border-b-black px-5 py-2 pt-5">
- <MobileSidebarItem
- logo={<HoarderLogoIcon className="w-5 fill-foreground" />}
- path="/dashboard/bookmarks"
- />
- <MobileSidebarItem logo={<Search />} path="/dashboard/search" />
- <MobileSidebarItem logo={<ClipboardList />} path="/dashboard/lists" />
- <MobileSidebarItem logo={<Tag />} path="/dashboard/tags" />
- <MobileSidebarItem
- logo={<Highlighter />}
- path="/dashboard/highlights"
- />
- </ul>
- </aside>
- );
-}
diff --git a/apps/web/components/dashboard/sidebar/Sidebar.tsx b/apps/web/components/dashboard/sidebar/Sidebar.tsx
deleted file mode 100644
index 0f805a09..00000000
--- a/apps/web/components/dashboard/sidebar/Sidebar.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-import { redirect } from "next/navigation";
-import SidebarItem from "@/components/shared/sidebar/SidebarItem";
-import { Separator } from "@/components/ui/separator";
-import { useTranslation } from "@/lib/i18n/server";
-import { api } from "@/server/api/client";
-import { getServerAuthSession } from "@/server/auth";
-import { Archive, Highlighter, Home, Search, Tag } from "lucide-react";
-
-import serverConfig from "@hoarder/shared/config";
-
-import AllLists from "./AllLists";
-
-export default async function Sidebar() {
- const { t } = await useTranslation();
- const session = await getServerAuthSession();
- if (!session) {
- redirect("/");
- }
-
- const lists = await api.lists.list();
-
- const searchItem = serverConfig.meilisearch
- ? [
- {
- name: t("common.search"),
- icon: <Search size={18} />,
- path: "/dashboard/search",
- },
- ]
- : [];
-
- const menu: {
- name: string;
- icon: JSX.Element;
- path: string;
- }[] = [
- {
- name: t("common.home"),
- icon: <Home size={18} />,
- path: "/dashboard/bookmarks",
- },
- ...searchItem,
- {
- name: t("common.tags"),
- icon: <Tag size={18} />,
- path: "/dashboard/tags",
- },
- {
- name: t("common.highlights"),
- icon: <Highlighter size={18} />,
- path: "/dashboard/highlights",
- },
- {
- name: t("common.archive"),
- icon: <Archive size={18} />,
- path: "/dashboard/archive",
- },
- ];
-
- return (
- <aside className="flex h-[calc(100vh-64px)] w-60 flex-col gap-5 border-r p-4 ">
- <div>
- <ul className="space-y-2 text-sm font-medium">
- {menu.map((item) => (
- <SidebarItem
- key={item.name}
- logo={item.icon}
- name={item.name}
- path={item.path}
- />
- ))}
- </ul>
- </div>
- <Separator />
- <AllLists initialData={lists} />
- <div className="mt-auto flex items-center border-t pt-2 text-sm text-gray-400">
- Hoarder v{serverConfig.serverVersion}
- </div>
- </aside>
- );
-}
diff --git a/apps/web/components/settings/sidebar/ModileSidebar.tsx b/apps/web/components/settings/sidebar/ModileSidebar.tsx
deleted file mode 100644
index cbed9ef9..00000000
--- a/apps/web/components/settings/sidebar/ModileSidebar.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import MobileSidebarItem from "@/components/shared/sidebar/ModileSidebarItem";
-import { useTranslation } from "@/lib/i18n/server";
-
-import { settingsSidebarItems } from "./items";
-
-export default async function MobileSidebar() {
- const { t } = await useTranslation();
- return (
- <aside className="w-full">
- <ul className="flex justify-between space-x-2 border-b-black px-5 py-2 pt-5">
- {settingsSidebarItems(t).map((item) => (
- <MobileSidebarItem
- key={item.name}
- logo={item.icon}
- path={item.path}
- />
- ))}
- </ul>
- </aside>
- );
-}
diff --git a/apps/web/components/settings/sidebar/Sidebar.tsx b/apps/web/components/settings/sidebar/Sidebar.tsx
deleted file mode 100644
index a1b61e98..00000000
--- a/apps/web/components/settings/sidebar/Sidebar.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import { redirect } from "next/navigation";
-import SidebarItem from "@/components/shared/sidebar/SidebarItem";
-import { useTranslation } from "@/lib/i18n/server";
-import { getServerAuthSession } from "@/server/auth";
-
-import serverConfig from "@hoarder/shared/config";
-
-import { settingsSidebarItems } from "./items";
-
-export default async function Sidebar() {
- const { t } = await useTranslation();
- const session = await getServerAuthSession();
- if (!session) {
- redirect("/");
- }
-
- return (
- <aside className="flex h-[calc(100vh-64px)] w-60 flex-col gap-5 border-r p-4 ">
- <div>
- <ul className="space-y-2 text-sm font-medium">
- {settingsSidebarItems(t).map((item) => (
- <SidebarItem
- key={item.name}
- logo={item.icon}
- name={item.name}
- path={item.path}
- />
- ))}
- </ul>
- </div>
- <div className="mt-auto flex items-center border-t pt-2 text-sm text-gray-400">
- Hoarder v{serverConfig.serverVersion}
- </div>
- </aside>
- );
-}
diff --git a/apps/web/components/settings/sidebar/items.tsx b/apps/web/components/settings/sidebar/items.tsx
deleted file mode 100644
index f76d494a..00000000
--- a/apps/web/components/settings/sidebar/items.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import React from "react";
-import { TFunction } from "i18next";
-import {
- ArrowLeft,
- Download,
- KeyRound,
- Link,
- Rss,
- Sparkles,
- User,
-} from "lucide-react";
-
-export const settingsSidebarItems = (
- t: TFunction,
-): {
- name: string;
- icon: JSX.Element;
- path: string;
-}[] => [
- {
- name: t("settings.back_to_app"),
- icon: <ArrowLeft size={18} />,
- path: "/dashboard/bookmarks",
- },
- {
- name: t("settings.info.user_info"),
- icon: <User size={18} />,
- path: "/settings/info",
- },
- {
- name: t("settings.ai.ai_settings"),
- icon: <Sparkles size={18} />,
- path: "/settings/ai",
- },
- {
- name: t("settings.feeds.rss_subscriptions"),
- icon: <Rss size={18} />,
- path: "/settings/feeds",
- },
- {
- name: t("settings.import.import_export"),
- icon: <Download size={18} />,
- path: "/settings/import",
- },
- {
- name: t("settings.api_keys.api_keys"),
- icon: <KeyRound size={18} />,
- path: "/settings/api-keys",
- },
- {
- name: t("settings.broken_links.broken_links"),
- icon: <Link size={18} />,
- path: "/settings/broken-links",
- },
-];
diff --git a/apps/web/components/admin/sidebar/MobileSidebar.tsx b/apps/web/components/shared/sidebar/MobileSidebar.tsx
index 416b944c..d3edc7df 100644
--- a/apps/web/components/admin/sidebar/MobileSidebar.tsx
+++ b/apps/web/components/shared/sidebar/MobileSidebar.tsx
@@ -1,14 +1,19 @@
-import MobileSidebarItem from "@/components/shared/sidebar/ModileSidebarItem";
import { useTranslation } from "@/lib/i18n/server";
+import { TFunction } from "i18next";
-import { adminSidebarItems } from "./items";
+import MobileSidebarItem from "./ModileSidebarItem";
+import { TSidebarItem } from "./TSidebarItem";
-export default async function MobileSidebar() {
+export default async function MobileSidebar({
+ items,
+}: {
+ items: (t: TFunction) => TSidebarItem[];
+}) {
const { t } = await useTranslation();
return (
<aside className="w-full">
<ul className="flex justify-between space-x-2 border-b-black px-5 py-2 pt-5">
- {adminSidebarItems(t).map((item) => (
+ {items(t).map((item) => (
<MobileSidebarItem
key={item.name}
logo={item.icon}
diff --git a/apps/web/components/admin/sidebar/Sidebar.tsx b/apps/web/components/shared/sidebar/Sidebar.tsx
index 8a5d615a..bd5d23e6 100644
--- a/apps/web/components/admin/sidebar/Sidebar.tsx
+++ b/apps/web/components/shared/sidebar/Sidebar.tsx
@@ -1,24 +1,25 @@
-import { redirect } from "next/navigation";
-import SidebarItem from "@/components/shared/sidebar/SidebarItem";
import { useTranslation } from "@/lib/i18n/server";
-import { getServerAuthSession } from "@/server/auth";
+import { TFunction } from "i18next";
import serverConfig from "@hoarder/shared/config";
-import { adminSidebarItems } from "./items";
+import SidebarItem from "./SidebarItem";
+import { TSidebarItem } from "./TSidebarItem";
-export default async function Sidebar() {
+export default async function Sidebar({
+ items,
+ extraSections,
+}: {
+ items: (t: TFunction) => TSidebarItem[];
+ extraSections?: React.ReactNode;
+}) {
const { t } = await useTranslation();
- const session = await getServerAuthSession();
- if (!session) {
- redirect("/");
- }
return (
<aside className="flex h-[calc(100vh-64px)] w-60 flex-col gap-5 border-r p-4 ">
<div>
<ul className="space-y-2 text-sm font-medium">
- {adminSidebarItems(t).map((item) => (
+ {items(t).map((item) => (
<SidebarItem
key={item.name}
logo={item.icon}
@@ -28,6 +29,7 @@ export default async function Sidebar() {
))}
</ul>
</div>
+ {extraSections}
<div className="mt-auto flex items-center border-t pt-2 text-sm text-gray-400">
Hoarder v{serverConfig.serverVersion}
</div>
diff --git a/apps/web/components/shared/sidebar/SidebarLayout.tsx b/apps/web/components/shared/sidebar/SidebarLayout.tsx
new file mode 100644
index 00000000..2a2a872e
--- /dev/null
+++ b/apps/web/components/shared/sidebar/SidebarLayout.tsx
@@ -0,0 +1,37 @@
+import Header from "@/components/dashboard/header/Header";
+import DemoModeBanner from "@/components/DemoModeBanner";
+import { Separator } from "@/components/ui/separator";
+import ValidAccountCheck from "@/components/utils/ValidAccountCheck";
+
+import serverConfig from "@hoarder/shared/config";
+
+export default function SidebarLayout({
+ children,
+ mobileSidebar,
+ sidebar,
+ modal,
+}: {
+ children: React.ReactNode;
+ mobileSidebar: React.ReactNode;
+ sidebar: React.ReactNode;
+ modal?: React.ReactNode;
+}) {
+ return (
+ <div>
+ <Header />
+ <div className="flex min-h-[calc(100vh-64px)] w-screen flex-col sm:h-[calc(100vh-64px)] sm:flex-row">
+ <ValidAccountCheck />
+ <div className="hidden flex-none sm:flex">{sidebar}</div>
+ <main className="flex-1 bg-muted sm:overflow-y-auto">
+ {serverConfig.demoMode && <DemoModeBanner />}
+ <div className="block w-full sm:hidden">
+ {mobileSidebar}
+ <Separator />
+ </div>
+ {modal}
+ <div className="min-h-30 container p-4">{children}</div>
+ </main>
+ </div>
+ </div>
+ );
+}
diff --git a/apps/web/components/shared/sidebar/TSidebarItem.ts b/apps/web/components/shared/sidebar/TSidebarItem.ts
new file mode 100644
index 00000000..84cd58f5
--- /dev/null
+++ b/apps/web/components/shared/sidebar/TSidebarItem.ts
@@ -0,0 +1,5 @@
+export interface TSidebarItem {
+ name: string;
+ icon: JSX.Element;
+ path: string;
+}