Skip to content

Commit 179257b

Browse files
committed
feat: demo sidebar fix, update config, clean up
1 parent 52d290e commit 179257b

24 files changed

+1023
-300
lines changed

apps/dashboard/app/demo/layout.tsx

Lines changed: 18 additions & 242 deletions
Original file line numberDiff line numberDiff line change
@@ -1,243 +1,12 @@
11
'use client';
22

3-
import {
4-
BugIcon,
5-
FunnelIcon,
6-
GlobeIcon,
7-
HouseIcon,
8-
InfoIcon,
9-
ListIcon,
10-
MapPinIcon,
11-
TargetIcon,
12-
UserIcon,
13-
UsersIcon,
14-
XIcon,
15-
} from '@phosphor-icons/react';
163
import { useAtom } from 'jotai';
17-
import Link from 'next/link';
18-
import { usePathname } from 'next/navigation';
19-
import { useCallback, useEffect, useState } from 'react';
204
import { toast } from 'sonner';
215
import { AnalyticsToolbar } from '@/app/(main)/websites/[id]/_components/analytics-toolbar';
22-
import { Logo } from '@/components/layout/logo';
23-
import { SignOutButton } from '@/components/layout/sign-out-button';
24-
import { ThemeToggle } from '@/components/layout/theme-toggle';
25-
import { NotificationsPopover } from '@/components/notifications/notifications-popover';
26-
import { Button } from '@/components/ui/button';
27-
import { ScrollArea } from '@/components/ui/scroll-area';
6+
import { Sidebar } from '@/components/layout/sidebar';
287
import { cn } from '@/lib/utils';
298
import { isAnalyticsRefreshingAtom } from '@/stores/jotai/filterAtoms';
309

31-
const DEMO_WEBSITE_ID = 'OXmNQsViBT-FOS_wZCTHc';
32-
const DEMO_WEBSITE_URL = 'https://www.databuddy.cc';
33-
34-
const demoNavigation = [
35-
{
36-
title: 'Web Analytics',
37-
items: [
38-
{
39-
name: 'Overview',
40-
icon: HouseIcon,
41-
href: `/demo/${DEMO_WEBSITE_ID}`,
42-
highlight: true,
43-
},
44-
{
45-
name: 'Sessions',
46-
icon: UserIcon,
47-
href: `/demo/${DEMO_WEBSITE_ID}/sessions`,
48-
highlight: true,
49-
},
50-
{
51-
name: 'Errors',
52-
icon: BugIcon,
53-
href: `/demo/${DEMO_WEBSITE_ID}/errors`,
54-
highlight: true,
55-
},
56-
{
57-
name: 'Map',
58-
icon: MapPinIcon,
59-
href: `/demo/${DEMO_WEBSITE_ID}/map`,
60-
highlight: true,
61-
},
62-
],
63-
},
64-
{
65-
title: 'Product Analytics',
66-
items: [
67-
{
68-
name: 'Profiles',
69-
icon: UsersIcon,
70-
href: `/demo/${DEMO_WEBSITE_ID}/profiles`,
71-
highlight: true,
72-
},
73-
{
74-
name: 'Funnels',
75-
icon: FunnelIcon,
76-
href: `/demo/${DEMO_WEBSITE_ID}/funnels`,
77-
highlight: true,
78-
},
79-
{
80-
name: 'Goals',
81-
icon: TargetIcon,
82-
href: `/demo/${DEMO_WEBSITE_ID}/goals`,
83-
highlight: true,
84-
},
85-
],
86-
},
87-
];
88-
89-
function Sidebar() {
90-
const pathname = usePathname();
91-
const [isMobileOpen, setIsMobileOpen] = useState(false);
92-
93-
const closeSidebar = useCallback(() => {
94-
setIsMobileOpen(false);
95-
}, []);
96-
97-
const handleKeyDown = useCallback(
98-
(e: KeyboardEvent) => {
99-
if (e.key === 'Escape' && isMobileOpen) {
100-
closeSidebar();
101-
}
102-
},
103-
[isMobileOpen, closeSidebar]
104-
);
105-
106-
useEffect(() => {
107-
document.addEventListener('keydown', handleKeyDown);
108-
return () => document.removeEventListener('keydown', handleKeyDown);
109-
}, [handleKeyDown]);
110-
111-
return (
112-
<>
113-
<header className="fixed top-0 right-0 left-0 z-50 h-16 w-full border-b bg-background/95 backdrop-blur-md">
114-
<div className="flex h-full items-center px-4 md:px-6">
115-
<div className="flex items-center gap-4">
116-
<Button
117-
aria-label="Toggle menu"
118-
className="md:hidden"
119-
onClick={() => setIsMobileOpen(true)}
120-
size="icon"
121-
variant="ghost"
122-
>
123-
<ListIcon className="h-5 w-5" weight="duotone" />
124-
</Button>
125-
126-
<div className="flex items-center gap-3">
127-
<Logo />
128-
</div>
129-
</div>
130-
131-
<div className="ml-auto flex items-center gap-2">
132-
<ThemeToggle />
133-
134-
<Button
135-
aria-label="Help"
136-
className="hidden h-8 w-8 md:flex"
137-
size="icon"
138-
variant="ghost"
139-
>
140-
<InfoIcon className="h-6 w-6" weight="duotone" />
141-
</Button>
142-
143-
<NotificationsPopover />
144-
<SignOutButton />
145-
</div>
146-
</div>
147-
</header>
148-
149-
{isMobileOpen && (
150-
<div
151-
aria-hidden="true"
152-
className="fixed inset-0 z-30 bg-black/20 md:hidden"
153-
onClick={closeSidebar}
154-
/>
155-
)}
156-
157-
<aside
158-
aria-label="Demo navigation"
159-
className={cn(
160-
'fixed inset-y-0 left-0 z-40 w-64 bg-background',
161-
'border-r pt-16 transition-transform duration-200 ease-out md:translate-x-0',
162-
isMobileOpen ? 'translate-x-0' : '-translate-x-full'
163-
)}
164-
>
165-
<Button
166-
aria-label="Close sidebar"
167-
className="absolute top-3 right-3 z-50 h-8 w-8 p-0 md:hidden"
168-
onClick={closeSidebar}
169-
size="sm"
170-
variant="ghost"
171-
>
172-
<XIcon className="h-4 w-4" weight="duotone" />
173-
</Button>
174-
175-
<ScrollArea className="h-[calc(100vh-4rem)]">
176-
<nav className="space-y-4 p-3">
177-
<div className="flex items-center gap-3 rounded border bg-muted/50 p-3">
178-
<div className="rounded border border-primary/20 bg-primary/10 p-2">
179-
<GlobeIcon
180-
aria-hidden="true"
181-
className="h-5 w-5 text-primary"
182-
weight="duotone"
183-
/>
184-
</div>
185-
<div className="min-w-0 flex-1">
186-
<h2 className="truncate font-semibold text-sm">Landing Page</h2>
187-
<Link
188-
className="truncate text-muted-foreground text-xs"
189-
href={DEMO_WEBSITE_URL}
190-
rel="noopener"
191-
target="_blank"
192-
>
193-
www.databuddy.cc
194-
</Link>
195-
</div>
196-
</div>
197-
198-
{demoNavigation.map((section) => (
199-
<div key={section.title}>
200-
<h3 className="mb-2 px-2 font-semibold text-muted-foreground text-xs uppercase tracking-wider">
201-
{section.title}
202-
</h3>
203-
<ul className="ml-1 space-y-1">
204-
{section.items.map((item) => {
205-
const isActive = pathname === item.href;
206-
const Icon = item.icon;
207-
208-
return (
209-
<li key={item.name}>
210-
<Link
211-
className={cn(
212-
'flex cursor-pointer items-center gap-3 rounded px-3 py-2 text-sm transition-all',
213-
isActive
214-
? 'bg-primary/15 font-medium text-primary'
215-
: 'text-foreground hover:bg-accent/70'
216-
)}
217-
href={item.href}
218-
>
219-
<Icon
220-
aria-hidden="true"
221-
className={cn(
222-
'h-4 w-4',
223-
isActive && 'text-primary'
224-
)}
225-
weight="duotone"
226-
/>
227-
<span className="truncate">{item.name}</span>
228-
</Link>
229-
</li>
230-
);
231-
})}
232-
</ul>
233-
</div>
234-
))}
235-
</nav>
236-
</ScrollArea>
237-
</aside>
238-
</>
239-
);
240-
}
24110

24211
interface MainLayoutProps {
24312
children: React.ReactNode;
@@ -260,20 +29,27 @@ export default function MainLayout({ children }: MainLayoutProps) {
26029
};
26130

26231
return (
263-
<div className="h-screen overflow-hidden bg-gradient-to-br from-background to-muted/20 text-foreground">
32+
<div className="h-screen overflow-hidden text-foreground">
26433
<Sidebar />
265-
<main className="relative h-screen pt-16 md:pl-64">
266-
<div className="h-[calc(100vh-4rem)] overflow-y-scroll">
267-
<div className="mx-auto max-w-[1600px] p-3 sm:p-4 lg:p-6">
268-
<AnalyticsToolbar
269-
isRefreshing={isRefreshing}
270-
onRefresh={handleRefresh}
271-
/>
34+
<div className="relative h-screen pl-0 md:pl-84">
35+
<div className="h-screen overflow-y-auto overflow-x-hidden pt-16 md:pt-0">
36+
<div
37+
className={cn(
38+
'mx-auto flex h-full max-w-[1600px] flex-col',
39+
'p-3 sm:p-4 lg:p-6'
40+
)}
41+
>
42+
<div className="flex-shrink-0 space-y-4">
43+
<AnalyticsToolbar
44+
isRefreshing={isRefreshing}
45+
onRefresh={handleRefresh}
46+
/>
47+
</div>
27248

273-
{children}
49+
<div className="min-h-0 flex-1">{children}</div>
27450
</div>
27551
</div>
276-
</main>
52+
</div>
27753
</div>
27854
);
27955
}

apps/dashboard/components/layout/category-sidebar.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
createLoadingDatabasesNavigation,
2222
createLoadingWebsitesNavigation,
2323
createWebsitesNavigation,
24+
filterCategoriesForRoute,
2425
getContextConfig,
2526
getDefaultCategory,
2627
} from './navigation/navigation-config';
@@ -69,8 +70,9 @@ export function CategorySidebar({
6970
: baseConfig;
7071

7172
const defaultCat = getDefaultCategory(pathname);
73+
const filteredCategories = filterCategoriesForRoute(config.categories, pathname);
7274

73-
return { categories: config.categories, defaultCategory: defaultCat };
75+
return { categories: filteredCategories, defaultCategory: defaultCat };
7476
}, [pathname, websites, isLoadingWebsites, databases, isLoadingDatabases]);
7577

7678
const activeCategory = selectedCategory || defaultCategory;

apps/dashboard/components/layout/navigation/mobile-category-selector.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
createLoadingDatabasesNavigation,
2020
createLoadingWebsitesNavigation,
2121
createWebsitesNavigation,
22+
filterCategoriesForRoute,
2223
getContextConfig,
2324
getDefaultCategory,
2425
} from './navigation-config';
@@ -56,7 +57,9 @@ export function MobileCategorySelector({
5657
: baseConfig;
5758

5859
const defaultCat = getDefaultCategory(pathname);
59-
return { categories: config.categories, defaultCategory: defaultCat };
60+
const filteredCategories = filterCategoriesForRoute(config.categories, pathname);
61+
62+
return { categories: filteredCategories, defaultCategory: defaultCat };
6063
}, [pathname, websites, isLoadingWebsites, databases, isLoadingDatabases]);
6164

6265
const activeCategory = selectedCategory || defaultCategory;

0 commit comments

Comments
 (0)