diff --git a/apps/web/public/locales/en/app.json b/apps/web/public/locales/en/app.json
index f49d21e8b..ca4c6bf58 100644
--- a/apps/web/public/locales/en/app.json
+++ b/apps/web/public/locales/en/app.json
@@ -122,7 +122,6 @@
"editDetailsDescription": "Change the details of your event.",
"finalizeDescription": "Select a final date for your event.",
"notificationsGuestTooltip": "Create an account or login to turn on notifications",
- "planFree": "Free",
"dateAndTimeDescription": "Change your preferred date and time settings",
"createdTime": "Created {relativeTime}",
"permissionDeniedParticipant": "If you are not the poll creator, you should go to the Invite Page.",
@@ -396,5 +395,10 @@
"actionErrorNotFound": "The resource was not found",
"actionErrorForbidden": "You are not allowed to perform this action",
"actionErrorInternalServerError": "An internal server error occurred",
- "cancelEvent": "Cancel Event"
+ "cancelEvent": "Cancel Event",
+ "createSpace": "Create Space",
+ "createSpaceDescription": "Create a new space to organize your polls and events.",
+ "createSpaceLoading": "Creating space...",
+ "createSpaceSuccess": "Space created successfully",
+ "createSpaceError": "Failed to create space"
}
diff --git a/apps/web/src/app/[locale]/(space)/components/sidebar/nav-item.tsx b/apps/web/src/app/[locale]/(space)/components/sidebar/nav-item.tsx
deleted file mode 100644
index 5212f11bd..000000000
--- a/apps/web/src/app/[locale]/(space)/components/sidebar/nav-item.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-"use client";
-
-import { SidebarMenuButton, SidebarMenuItem } from "@rallly/ui/sidebar";
-import Link from "next/link";
-import { usePathname } from "next/navigation";
-
-export function NavItem({
- href,
- children,
-}: {
- href: string;
- children: React.ReactNode;
-}) {
- const pathname = usePathname();
- const isActive = pathname === href;
-
- return (
-
-
- {children}
-
-
- );
-}
diff --git a/apps/web/src/app/[locale]/(space)/components/sidebar/nav-user.tsx b/apps/web/src/app/[locale]/(space)/components/sidebar/nav-user.tsx
index a4ed6040e..3aa056609 100644
--- a/apps/web/src/app/[locale]/(space)/components/sidebar/nav-user.tsx
+++ b/apps/web/src/app/[locale]/(space)/components/sidebar/nav-user.tsx
@@ -24,7 +24,7 @@ export function NavUser({
{name}
-
+
{plan}
diff --git a/apps/web/src/app/[locale]/(space)/components/sidebar/space-sidebar-menu.tsx b/apps/web/src/app/[locale]/(space)/components/sidebar/space-sidebar-menu.tsx
new file mode 100644
index 000000000..ab99d1374
--- /dev/null
+++ b/apps/web/src/app/[locale]/(space)/components/sidebar/space-sidebar-menu.tsx
@@ -0,0 +1,52 @@
+"use client";
+
+import { useTranslation } from "@/i18n/client";
+import { Icon } from "@rallly/ui/icon";
+import {
+ SidebarMenu,
+ SidebarMenuButton,
+ SidebarMenuItem,
+} from "@rallly/ui/sidebar";
+import { BarChart2Icon, CalendarIcon, HomeIcon } from "lucide-react";
+import Link from "next/link";
+import { usePathname } from "next/navigation";
+
+const useSpaceMenuItems = () => {
+ const { t } = useTranslation();
+ return [
+ {
+ href: "/",
+ icon: ,
+ label: t("home", { defaultValue: "Home" }),
+ },
+ {
+ href: "/polls",
+ icon: ,
+ label: t("polls", { defaultValue: "Polls" }),
+ },
+ {
+ href: "/events",
+ icon: ,
+ label: t("events", { defaultValue: "Events" }),
+ },
+ ];
+};
+
+export function SpaceSidebarMenu() {
+ const items = useSpaceMenuItems();
+ const pathname = usePathname();
+ return (
+
+ {items.map((item) => (
+
+
+
+ {item.icon}
+ {item.label}
+
+
+
+ ))}
+
+ );
+}
diff --git a/apps/web/src/app/[locale]/(space)/components/sidebar/app-sidebar-provider.tsx b/apps/web/src/app/[locale]/(space)/components/sidebar/space-sidebar-provider.tsx
similarity index 92%
rename from apps/web/src/app/[locale]/(space)/components/sidebar/app-sidebar-provider.tsx
rename to apps/web/src/app/[locale]/(space)/components/sidebar/space-sidebar-provider.tsx
index f7c9e0f6f..da60a034a 100644
--- a/apps/web/src/app/[locale]/(space)/components/sidebar/app-sidebar-provider.tsx
+++ b/apps/web/src/app/[locale]/(space)/components/sidebar/space-sidebar-provider.tsx
@@ -3,7 +3,7 @@
import { SidebarProvider } from "@rallly/ui/sidebar";
import { useLocalStorage } from "react-use";
-export function AppSidebarProvider({
+export function SpaceSidebarProvider({
children,
}: {
children: React.ReactNode;
diff --git a/apps/web/src/app/[locale]/(space)/components/sidebar/app-sidebar.tsx b/apps/web/src/app/[locale]/(space)/components/sidebar/space-sidebar.tsx
similarity index 62%
rename from apps/web/src/app/[locale]/(space)/components/sidebar/app-sidebar.tsx
rename to apps/web/src/app/[locale]/(space)/components/sidebar/space-sidebar.tsx
index d4c2d21e6..eb805af3e 100644
--- a/apps/web/src/app/[locale]/(space)/components/sidebar/app-sidebar.tsx
+++ b/apps/web/src/app/[locale]/(space)/components/sidebar/space-sidebar.tsx
@@ -1,3 +1,12 @@
+import { SpaceSidebarMenu } from "@/app/[locale]/(space)/components/sidebar/space-sidebar-menu";
+import { LogoLink } from "@/app/components/logo-link";
+import { getActiveSpace, requireUserAbility } from "@/auth/queries";
+import { Trans } from "@/components/trans";
+import { FeedbackToggle } from "@/features/feedback/components/feedback-toggle";
+import { SpaceDropdown } from "@/features/spaces/components/space-dropdown";
+import { SpaceIcon } from "@/features/spaces/components/space-icon";
+import { isSpacesEnabled } from "@/features/spaces/constants";
+import { loadSpaces } from "@/features/spaces/queries";
import { Button } from "@rallly/ui/button";
import { Icon } from "@rallly/ui/icon";
import {
@@ -6,33 +15,34 @@ import {
SidebarFooter,
SidebarGroup,
SidebarHeader,
- SidebarMenu,
SidebarSeparator,
} from "@rallly/ui/sidebar";
import { Tooltip, TooltipContent, TooltipTrigger } from "@rallly/ui/tooltip";
-import {
- BarChart2Icon,
- CalendarIcon,
- HomeIcon,
- PlusIcon,
- SparklesIcon,
-} from "lucide-react";
+import { ChevronsUpDownIcon, PlusIcon, SparklesIcon } from "lucide-react";
import Link from "next/link";
-import type * as React from "react";
-
-import { LogoLink } from "@/app/components/logo-link";
-import { Trans } from "@/components/trans";
-import { FeedbackToggle } from "@/features/feedback/components/feedback-toggle";
-
-import { requireUser } from "@/auth/queries";
+import type React from "react";
import { UpgradeButton } from "../upgrade-button";
-import { NavItem } from "./nav-item";
import { NavUser } from "./nav-user";
-export async function AppSidebar({
+async function loadData() {
+ const [{ user }, spaces, activeSpace] = await Promise.all([
+ requireUserAbility(),
+ loadSpaces(),
+ getActiveSpace(),
+ ]);
+
+ return {
+ user,
+ spaces,
+ activeSpace,
+ };
+}
+
+export async function SpaceSidebar({
...props
}: React.ComponentProps) {
- const user = await requireUser();
+ const { user, spaces, activeSpace } = await loadData();
+
return (
@@ -58,23 +68,28 @@ export async function AppSidebar({