Refactor dashboard with smart redirect and AllSearchSpacesSheet

This commit is contained in:
CREDO23 2026-01-12 16:38:40 +02:00
parent 7a58f2f568
commit 38fd1995aa
6 changed files with 288 additions and 388 deletions

View file

@ -8,6 +8,7 @@ import { useTranslations } from "next-intl";
import { useTheme } from "next-themes";
import { useCallback, useMemo, useState } from "react";
import { hasUnsavedEditorChangesAtom, pendingEditorNavigationAtom } from "@/atoms/editor/ui.atoms";
import { deleteSearchSpaceMutationAtom } from "@/atoms/search-spaces/search-space-mutation.atoms";
import { searchSpacesAtom } from "@/atoms/search-spaces/search-space-query.atoms";
import { currentUserAtom } from "@/atoms/user/user-query.atoms";
import { Button } from "@/components/ui/button";
@ -26,7 +27,9 @@ import { deleteThread, fetchThreads } from "@/lib/chat/thread-persistence";
import { resetUser, trackLogout } from "@/lib/posthog/events";
import { cacheKeys } from "@/lib/query-client/cache-keys";
import type { ChatItem, NavItem, NoteItem, SearchSpace } from "../types/layout.types";
import { CreateSearchSpaceDialog } from "../ui/dialogs";
import { LayoutShell } from "../ui/shell";
import { AllSearchSpacesSheet } from "../ui/sheets";
import { AllChatsSidebar } from "../ui/sidebar/AllChatsSidebar";
import { AllNotesSidebar } from "../ui/sidebar/AllNotesSidebar";
@ -53,7 +56,8 @@ export function LayoutDataProvider({
// Atoms
const { data: user } = useAtomValue(currentUserAtom);
const { data: searchSpacesData } = useAtomValue(searchSpacesAtom);
const { data: searchSpacesData, refetch: refetchSearchSpaces } = useAtomValue(searchSpacesAtom);
const { mutateAsync: deleteSearchSpace } = useAtomValue(deleteSearchSpaceMutationAtom);
const hasUnsavedEditorChanges = useAtomValue(hasUnsavedEditorChangesAtom);
const setPendingNavigation = useSetAtom(pendingEditorNavigationAtom);
@ -110,6 +114,10 @@ export function LayoutDataProvider({
const [isAllChatsSidebarOpen, setIsAllChatsSidebarOpen] = useState(false);
const [isAllNotesSidebarOpen, setIsAllNotesSidebarOpen] = useState(false);
// Search space sheet and dialog state
const [isAllSearchSpacesSheetOpen, setIsAllSearchSpacesSheetOpen] = useState(false);
const [isCreateSearchSpaceDialogOpen, setIsCreateSearchSpaceDialogOpen] = useState(false);
// Delete dialogs state
const [showDeleteChatDialog, setShowDeleteChatDialog] = useState(false);
const [chatToDelete, setChatToDelete] = useState<{ id: number; name: string } | null>(null);
@ -123,7 +131,6 @@ export function LayoutDataProvider({
} | null>(null);
const [isDeletingNote, setIsDeletingNote] = useState(false);
// Transform search spaces (API returns array directly, not { items: [...] })
const searchSpaces: SearchSpace[] = useMemo(() => {
if (!searchSpacesData || !Array.isArray(searchSpacesData)) return [];
return searchSpacesData.map((space) => ({
@ -132,6 +139,7 @@ export function LayoutDataProvider({
description: space.description,
isOwner: space.is_owner,
memberCount: space.member_count || 0,
createdAt: space.created_at,
}));
}, [searchSpacesData]);
@ -204,12 +212,35 @@ export function LayoutDataProvider({
);
const handleAddSearchSpace = useCallback(() => {
router.push("/dashboard/searchspaces");
}, [router]);
setIsCreateSearchSpaceDialogOpen(true);
}, []);
const handleSeeAllSearchSpaces = useCallback(() => {
router.push("/dashboard");
}, [router]);
setIsAllSearchSpacesSheetOpen(true);
}, []);
const handleSearchSpaceSettings = useCallback(
(id: number) => {
router.push(`/dashboard/${id}/settings`);
},
[router]
);
const handleDeleteSearchSpace = useCallback(
async (id: number) => {
await deleteSearchSpace({ id });
refetchSearchSpaces();
if (Number(searchSpaceId) === id && searchSpaces.length > 1) {
const remaining = searchSpaces.filter((s) => s.id !== id);
if (remaining.length > 0) {
router.push(`/dashboard/${remaining[0].id}/new-chat`);
}
} else if (searchSpaces.length === 1) {
router.push("/dashboard");
}
},
[deleteSearchSpace, refetchSearchSpaces, searchSpaceId, searchSpaces, router]
);
const handleNavItemClick = useCallback(
(item: NavItem) => {
@ -439,6 +470,26 @@ export function LayoutDataProvider({
onAddNote={handleAddNote}
/>
{/* All Search Spaces Sheet */}
<AllSearchSpacesSheet
open={isAllSearchSpacesSheetOpen}
onOpenChange={setIsAllSearchSpacesSheetOpen}
searchSpaces={searchSpaces}
onSearchSpaceSelect={handleSearchSpaceSelect}
onCreateNew={() => {
setIsAllSearchSpacesSheetOpen(false);
setIsCreateSearchSpaceDialogOpen(true);
}}
onSettings={handleSearchSpaceSettings}
onDelete={handleDeleteSearchSpace}
/>
{/* Create Search Space Dialog */}
<CreateSearchSpaceDialog
open={isCreateSearchSpaceDialogOpen}
onOpenChange={setIsCreateSearchSpaceDialogOpen}
/>
{/* Delete Note Dialog */}
<Dialog open={showDeleteNoteDialog} onOpenChange={setShowDeleteNoteDialog}>
<DialogContent className="sm:max-w-md">