Commit cd7baf59 authored by Dimitrios Gogos's avatar Dimitrios Gogos
Browse files

feat: rework profile page, navigation, minor fixes

parent dc37e731
Loading
Loading
Loading
Loading
+21 −16
Changes for portal-gui/src/app/config/navigation.ts: 21 added lines, 16 removed lines.
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ import {
  FileText,
  Server,
  Rocket,
  UserIcon,
} from 'lucide-react';

import { ROUTES } from './route';
@@ -55,6 +56,12 @@ export const mainNavItems: NavItem[] = [
      },
    ],
  },
  {
    title: 'Profile',
    to: ROUTES.PROFILE,
    description: 'Your account details and portal roles.',
    icon: UserIcon,
  },
];

export function isActivePath(pathname: string, to: string) {
@@ -89,23 +96,21 @@ export function findNavPath(
}

export function getBreadcrumbItems(pathname: string): BreadcrumbItem[] {
  const navPath = findNavPath(mainNavItems, pathname);
  if (!navPath) {
    return [
      {
        title: 'Home',
        to: ROUTES.HOME,
      },
    ];
  // Detail pages such as /apis/:id are not in the nav, so walk up to the
  // nearest page that is.
  let navPath: NavItem[] | null = null;
  for (
    let path = pathname;
    !navPath && path;
    path = path.slice(0, path.lastIndexOf('/'))
  ) {
    navPath = findNavPath(mainNavItems, path);
  }
  return [
    {
      title: 'Home',
      to: ROUTES.HOME,
    },
    ...navPath.map((item) => ({
  const trail = (navPath ?? []).map((item) => ({
    title: item.title,
    to: item.to,
    })),
  ];
  }));
  return trail[0]?.to === ROUTES.HOME
    ? trail
    : [{ title: 'Home', to: ROUTES.HOME }, ...trail];
}
+1 −1
Changes for portal-gui/src/app/config/route.ts: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@ export const ROUTES = {
  HOME: '/',
  LOGIN: '/login',

  SETTINGS: '/settings',
  PROFILE: '/profile',
  APIS: '/apis',
  API: '/apis/:id',
  APPLICATIONS: '/applications',
+3 −9
Changes for portal-gui/src/app/router.tsx: 3 added lines, 9 removed lines.
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@ import { PublicRoute } from './guards/public-route';

// Pages
import HomePage from '@/pages/home/index';
import SettingsPage from '@/pages/settings';
import ProfilePage from '@/pages/profile';
import LoginPage from '@/pages/auth/login';
import ApisPage from '@/pages/apis/';
import ApiDetailsPage from '@/pages/apis/api-details';
@@ -23,8 +23,6 @@ import NotFoundPage from '@/pages/errors/not-found';

import { ROUTES } from './config/route';

import { RoleGuard } from './guards/role-guard';

export const router = createBrowserRouter([
  // Public routes
  {
@@ -53,12 +51,8 @@ export const router = createBrowserRouter([
            element: <HomePage />,
          },
          {
            path: ROUTES.SETTINGS,
            element: (
              <RoleGuard allowedRoles={['platform-admin']}>
                <SettingsPage />
              </RoleGuard>
            ),
            path: ROUTES.PROFILE,
            element: <ProfilePage />,
          },
          {
            path: ROUTES.APIS,
+2 −1
Changes for portal-gui/src/components/common/app-breadcrumbs.tsx: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -20,11 +20,12 @@ export function AppBreadcrumbs() {
      <BreadcrumbList>
        {items.map((item, index) => {
          const isLast = index === items.length - 1;
          const isCurrent = item.to === pathname;

          return (
            <Fragment key={`{item.title}-${index}`}>
              <BreadcrumbItem>
                {isLast ? (
                {isCurrent ? (
                  <BreadcrumbPage>{item.title}</BreadcrumbPage>
                ) : (
                  <BreadcrumbLink asChild>
+47 −21
Changes for portal-gui/src/components/common/nav-main.tsx: 47 added lines, 21 removed lines.
Original line number Diff line number Diff line
import { useState } from 'react';
import { Link, useLocation } from 'react-router-dom';
import { ChevronRight } from 'lucide-react';
import { isActivePath } from '@/app/config/navigation';
@@ -6,6 +7,7 @@ import {
  SidebarGroup,
  SidebarGroupContent,
  SidebarMenu,
  SidebarMenuAction,
  SidebarMenuButton,
  SidebarMenuItem,
  SidebarMenuSub,
@@ -47,26 +49,58 @@ export function NavMain({ items }: { items: NavItem[] }) {
                </SidebarMenuItem>
              );
            }
            // Navigation item with children
            const childIsActive = item.children!.some((child) =>
              isActivePath(pathname, child.to),
            return (
              <NavGroup
                key={item.to}
                item={item}
                pathname={pathname}
                onNavigate={() => setOpenMobile(false)}
              />
            );
          })}
        </SidebarMenu>
      </SidebarGroupContent>
    </SidebarGroup>
  );
}

type NavGroupProps = {
  item: NavItem;
  pathname: string;
  onNavigate: () => void;
};

// The label opens the section's page; the chevron only expands the submenu.
function NavGroup({ item, pathname, onNavigate }: NavGroupProps) {
  const isActive = isActivePath(pathname, item.to);
  const [open, setOpen] = useState(isActive);
  const Icon = item.icon;

  return (
              <SidebarMenuItem key={item.to}>
                <Collapsible
                  defaultOpen={childIsActive}
                  className="group/collapsible"
                >
                  <CollapsibleTrigger asChild>
    <Collapsible open={open} onOpenChange={setOpen} asChild>
      <SidebarMenuItem>
        <SidebarMenuButton
          asChild
          isActive={isActive}
          tooltip={item.title}
                      isActive={childIsActive}
          className="text-muted-foreground hover:text-foreground data-[active=true]:text-primary"
        >
          <Link
            to={item.to}
            onClick={() => {
              setOpen(true);
              onNavigate();
            }}
          >
            <Icon />
            <span>{item.title}</span>
                      <ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
          </Link>
        </SidebarMenuButton>
        <CollapsibleTrigger asChild>
          <SidebarMenuAction className="data-[state=open]:rotate-90">
            <ChevronRight />
            <span className="sr-only">Toggle {item.title}</span>
          </SidebarMenuAction>
        </CollapsibleTrigger>
        <CollapsibleContent>
          <SidebarMenuSub>
@@ -79,10 +113,7 @@ export function NavMain({ items }: { items: NavItem[] }) {
                    asChild
                    isActive={pathname === child.to}
                  >
                              <Link
                                to={child.to}
                                onClick={() => setOpenMobile(false)}
                              >
                    <Link to={child.to} onClick={onNavigate}>
                      <ChildIcon />
                      <span>{child.title}</span>
                    </Link>
@@ -92,12 +123,7 @@ export function NavMain({ items }: { items: NavItem[] }) {
            })}
          </SidebarMenuSub>
        </CollapsibleContent>
                </Collapsible>
      </SidebarMenuItem>
            );
          })}
        </SidebarMenu>
      </SidebarGroupContent>
    </SidebarGroup>
    </Collapsible>
  );
}
Loading