Skip to content

Commit ecf5aec

Browse files
committed
chore: Refactor instance nav bar to be DRY
1 parent 839fe49 commit ecf5aec

File tree

1 file changed

+64
-59
lines changed

1 file changed

+64
-59
lines changed

src/features/instance/InstanceNavBar.tsx

Lines changed: 64 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -9,51 +9,78 @@ import {
99
DropdownMenuTrigger,
1010
} from '@/components/ui/dropdownMenu';
1111
import { useInstanceManagePermission } from '@/hooks/usePermissions';
12+
import { excludeFalsy } from '@/lib/arrays/excludeFalsy';
1213
import { buildAbsoluteLinkToPage } from '@/lib/urls/buildAbsoluteLinkToPage';
1314
import { Link, useParams } from '@tanstack/react-router';
14-
import { DatabaseIcon, GaugeIcon, Menu, NotepadText, Package, SettingsIcon } from 'lucide-react';
15+
import { DatabaseIcon, GaugeIcon, Menu, NotepadTextIcon, PackageIcon, SettingsIcon } from 'lucide-react';
16+
import { ReactNode, useMemo } from 'react';
1517

16-
function DesktopInstanceNavBar() {
18+
interface Link {
19+
to: string;
20+
name: string;
21+
shortName?: string;
22+
icon: ReactNode;
23+
}
24+
25+
export function InstanceNavBar() {
1726
const canManage = useInstanceManagePermission();
1827
const params = useParams({ strict: false });
28+
const links = useMemo(() => [
29+
{
30+
to: buildAbsoluteLinkToPage(params),
31+
name: 'Applications',
32+
shortName: 'Apps',
33+
icon: <PackageIcon className="inline-block" />,
34+
},
35+
{
36+
to: buildAbsoluteLinkToPage(params, 'databases'),
37+
icon: <DatabaseIcon className="inline-block" />,
38+
name: 'Databases',
39+
},
40+
canManage && {
41+
to: buildAbsoluteLinkToPage(params, 'status'),
42+
icon: <GaugeIcon className="inline-block" />,
43+
name: 'Status',
44+
},
45+
canManage && {
46+
to: buildAbsoluteLinkToPage(params, 'logs'),
47+
icon: <NotepadTextIcon className="inline-block" />,
48+
name: 'Logs',
49+
},
50+
canManage && {
51+
to: buildAbsoluteLinkToPage(params, 'config'),
52+
icon: <SettingsIcon className="inline-block" />,
53+
name: 'Config',
54+
},
55+
].filter(excludeFalsy) satisfies Link[], [canManage, params]);
56+
return (
57+
<>
58+
<DesktopInstanceNavBar links={links} />
59+
<MobileInstanceNavBar links={links} />
60+
</>
61+
);
62+
}
63+
64+
function DesktopInstanceNavBar({ links }: { links: Link[] }) {
1965
return (
2066
<div className="hidden md:flex items-center justify-between h-full text-sm text-white">
2167
<Breadcrumbs />
2268
<div className="flex space-x-2 *:hover:text-grey">
23-
<Link to={buildAbsoluteLinkToPage(params)} className="p-2 text-center">
24-
<Package className="inline-block" />
25-
<span className="hidden xl:inline-block ml-1">Applications</span>
26-
<span className="visible xl:hidden ml-1"> Apps</span>
27-
28-
</Link>
29-
<Link to={buildAbsoluteLinkToPage(params, 'databases')} className="p-2 text-center">
30-
<DatabaseIcon className="inline-block" />
31-
<span className="hidden xl:inline-block ml-1"> Databases</span>
32-
</Link>
33-
{canManage && (
34-
<>
35-
<Link to={buildAbsoluteLinkToPage(params, 'status')} className="p-2 text-center">
36-
<GaugeIcon className="inline-block" />
37-
<span className="hidden xl:inline-block ml-1">Status</span>
38-
</Link>
39-
<Link to={buildAbsoluteLinkToPage(params, 'logs')} className="p-2 text-center">
40-
<NotepadText className="inline-block" />
41-
<span className="hidden xl:inline-block ml-1">Logs</span>
42-
</Link>
43-
<Link to={buildAbsoluteLinkToPage(params, 'config')} className="p-2 text-center">
44-
<SettingsIcon className="inline-block" />
45-
<span className="hidden xl:inline-block ml-1">Config</span>
46-
</Link>
47-
</>
48-
)}
69+
{links.map(link => (
70+
<Link key={link.to} to={link.to} className="p-2 text-center">
71+
{link.icon}
72+
<span className="hidden xl:inline-block ml-1">{link.name}</span>
73+
{link.shortName && (
74+
<span className="visible xl:hidden ml-1"> {link.shortName}</span>
75+
)}
76+
</Link>
77+
))}
4978
</div>
5079
</div>
5180
);
5281
}
5382

54-
function MobileInstanceNavBar() {
55-
const canManage = useInstanceManagePermission();
56-
const params = useParams({ strict: false });
83+
function MobileInstanceNavBar({ links }: { links: Link[] }) {
5784
return (
5885
<>
5986
<div className="flex md:hidden items-center justify-between p-2 text-white">
@@ -67,37 +94,15 @@ function MobileInstanceNavBar() {
6794
<DropdownMenuContent>
6895
<DropdownMenuLabel>Instance Menu</DropdownMenuLabel>
6996
<DropdownMenuSeparator />
70-
<DropdownMenuItem asChild>
71-
<Link to={buildAbsoluteLinkToPage(params)}>Applications</Link>
72-
</DropdownMenuItem>
73-
<DropdownMenuItem asChild>
74-
<Link to={buildAbsoluteLinkToPage(params, 'databases')}>Databases</Link>
75-
</DropdownMenuItem>
76-
{canManage && (
77-
<>
78-
<DropdownMenuItem asChild>
79-
<Link to={buildAbsoluteLinkToPage(params, 'status')}>Status</Link>
80-
</DropdownMenuItem>
81-
<DropdownMenuItem asChild>
82-
<Link to={buildAbsoluteLinkToPage(params, 'config')}>Config</Link>
83-
</DropdownMenuItem>
84-
<DropdownMenuItem asChild>
85-
<Link to={buildAbsoluteLinkToPage(params, 'logs')}>Logs</Link>
86-
</DropdownMenuItem>
87-
</>
88-
)}
97+
98+
{links.map(link => (
99+
<DropdownMenuItem key={link.to} asChild>
100+
<Link to={link.to}>{link.name}</Link>
101+
</DropdownMenuItem>
102+
))}
89103
</DropdownMenuContent>
90104
</DropdownMenu>
91105
</div>
92106
</>
93107
);
94108
}
95-
96-
export function InstanceNavBar() {
97-
return (
98-
<>
99-
<DesktopInstanceNavBar />
100-
<MobileInstanceNavBar />
101-
</>
102-
);
103-
}

0 commit comments

Comments
 (0)