Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@
"@fal-ai/client": "^1.6.2",
"@formkit/auto-animate": "^0.9.0",
"@google/genai": "^1.24.0",
"@huggingface/inference": "^4.11.3",
"@icons-pack/react-simple-icons": "^13.8.0",
"@khmyznikov/pwa-install": "0.3.9",
"@langchain/community": "^0.3.57",
Expand Down Expand Up @@ -262,6 +261,7 @@
"react-lazy-load": "^4.0.1",
"react-pdf": "^9.2.1",
"react-rnd": "^10.5.2",
"react-router-dom": "^7.9.4",
"react-scan": "^0.4.3",
"react-virtuoso": "^4.14.1",
"react-wrap-balancer": "^1.1.1",
Expand Down
40 changes: 0 additions & 40 deletions src/app/[variants]/(main)/profile/(home)/[[...slugs]]/page.tsx

This file was deleted.

17 changes: 0 additions & 17 deletions src/app/[variants]/(main)/profile/@category/default.tsx

This file was deleted.

This file was deleted.

90 changes: 90 additions & 0 deletions src/app/[variants]/(main)/profile/ProfileRouter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
'use client';

import { useResponsive } from 'antd-style';
import { memo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { Flexbox } from 'react-layout-kit';
import { BrowserRouter, Route, Routes, useLocation } from 'react-router-dom';

import InitClientDB from '@/features/InitClientDB';
import Footer from '@/features/Setting/Footer';
import SettingContainer from '@/features/Setting/SettingContainer';

import Header from './_layout/Desktop/Header';
import SideBar from './_layout/Desktop/SideBar';
import CategoryContent from './features/CategoryContent';
import ApiKeyPage from './routes/ApiKeyPage';
import ProfilePage from './routes/ProfilePage';
import SecurityPage from './routes/SecurityPage';
import StatsPage from './routes/StatsPage';

interface ProfileLayoutProps {
mobile?: boolean;
}

const ProfileLayout = memo<ProfileLayoutProps>(({ mobile }) => {
const ref = useRef<any>(null);
const { md = true } = useResponsive();
const { t } = useTranslation('auth');
const location = useLocation();

// Get active tab from pathname
const getActiveTab = () => {
const path = location.pathname.replace('/profile', '').replace(/^\//, '');
if (!path) return 'profile';
return path;
};

const activeKey = getActiveTab();

return (
<>
<Flexbox
height={'100%'}
horizontal={md}
ref={ref}
style={{ position: 'relative' }}
width={'100%'}
>
{md ? (
<SideBar>
<CategoryContent />
</SideBar>
) : (
<Header getContainer={() => ref.current} title={<>{t(`tab.${activeKey}` as any)}</>}>
<CategoryContent />
</Header>
)}
<SettingContainer
addonAfter={<Footer />}
style={{
paddingBlock: 24,
paddingInline: 32,
}}
>
<Routes>
<Route element={<ProfilePage mobile={mobile} />} path="/" />
<Route element={<StatsPage mobile={mobile} />} path="/stats" />
<Route element={<ApiKeyPage />} path="/apikey" />
<Route element={<SecurityPage mobile={mobile} />} path="/security" />
</Routes>
</SettingContainer>
</Flexbox>
<InitClientDB />
</>
);
});

ProfileLayout.displayName = 'ProfileLayout';

const ProfileRouter = memo<ProfileLayoutProps>(({ mobile }) => {
return (
<BrowserRouter basename="/profile">
<ProfileLayout mobile={mobile} />
</BrowserRouter>
);
});

ProfileRouter.displayName = 'ProfileRouter';

export default ProfileRouter;
19 changes: 19 additions & 0 deletions src/app/[variants]/(main)/profile/[[...slugs]]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use client';

import dynamic from 'next/dynamic';

import BrandTextLoading from '@/components/Loading/BrandTextLoading';
import { useIsMobile } from '@/hooks/useIsMobile';

const ProfileRouter = dynamic(() => import('../ProfileRouter'), {
loading: BrandTextLoading,
ssr: false,
});

const Page = () => {
const mobile = useIsMobile();

return <ProfileRouter mobile={mobile} />;
};

export default Page;
32 changes: 0 additions & 32 deletions src/app/[variants]/(main)/profile/apikey/page.tsx

This file was deleted.

31 changes: 31 additions & 0 deletions src/app/[variants]/(main)/profile/features/CategoryContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use client';

import { memo } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';

import Menu from '@/components/Menu';
import { ProfileTabs } from '@/store/global/initialState';

import { useCategory } from '../hooks/useCategory';

const CategoryContent = memo(() => {
const location = useLocation();
const navigate = useNavigate();
const activeTab = location.pathname.replace(/^\//, '') || 'profile';
const cateItems = useCategory();

return (
<Menu
compact
items={cateItems}
onClick={({ key }) => {
const activeKey = key === ProfileTabs.Profile ? '/' : `/${key}`;
navigate(activeKey);
}}
selectable
selectedKeys={activeTab === '' ? ['profile'] : [activeTab]}
/>
);
});

export default CategoryContent;
27 changes: 5 additions & 22 deletions src/app/[variants]/(main)/profile/hooks/useCategory.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Icon } from '@lobehub/ui';
import { ChartColumnBigIcon, KeyIcon, ShieldCheck, UserCircle } from 'lucide-react';
import Link from 'next/link';
import { useTranslation } from 'react-i18next';

import type { MenuProps } from '@/components/Menu';
Expand All @@ -20,39 +19,23 @@ export const useCategory = () => {
{
icon: <Icon icon={UserCircle} />,
key: ProfileTabs.Profile,
label: (
<Link href={'/profile'} onClick={(e) => e.preventDefault()}>
{t('tab.profile')}
</Link>
),
label: t('tab.profile'),
},
enableAuth &&
isLoginWithClerk && {
icon: <Icon icon={ShieldCheck} />,
key: ProfileTabs.Security,
label: (
<Link href={'/profile/security'} onClick={(e) => e.preventDefault()}>
{t('tab.security')}
</Link>
),
label: t('tab.security'),
},
!isDeprecatedEdition && {
icon: <Icon icon={ChartColumnBigIcon} />,
key: ProfileTabs.Stats,
label: (
<Link href={'/profile/stats'} onClick={(e) => e.preventDefault()}>
{t('tab.stats')}
</Link>
),
},
label: t('tab.stats'),
},
!!showApiKeyManage && {
icon: <Icon icon={KeyIcon} />,
key: ProfileTabs.APIKey,
label: (
<Link href={'/profile/apikey'} onClick={(e) => e.preventDefault()}>
{t('tab.apikey')}
</Link>
),
label: t('tab.apikey'),
},
].filter(Boolean) as MenuProps['items'];

Expand Down
10 changes: 4 additions & 6 deletions src/app/[variants]/(main)/profile/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import ServerLayout from '@/components/server/ServerLayout';
import { PropsWithChildren } from 'react';

import Desktop from './_layout/Desktop';
import Mobile from './_layout/Mobile';
import { LayoutProps } from './_layout/type';

const ProfileLayout = ServerLayout<LayoutProps>({ Desktop, Mobile });
const ProfileLayout = ({ children }: PropsWithChildren) => {
return children;
};

ProfileLayout.displayName = 'ProfileLayout';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { useTranslation } from 'react-i18next';
import { lambdaClient } from '@/libs/trpc/client';
import { ApiKeyItem, CreateApiKeyParams, UpdateApiKeyParams } from '@/types/apiKey';

import { ApiKeyDisplay, ApiKeyModal, EditableCell } from './features';
import { ApiKeyDisplay, ApiKeyModal, EditableCell } from '../apikey/features';

const useStyles = createStyles(({ css, token }) => ({
container: css`
Expand All @@ -35,7 +35,7 @@ const useStyles = createStyles(({ css, token }) => ({
`,
}));

const Client: FC = () => {
const ApiKeyPage: FC = () => {
const { styles } = useStyles();
const { t } = useTranslation('auth');
const [modalOpen, setModalOpen] = useState(false);
Expand Down Expand Up @@ -206,4 +206,4 @@ const Client: FC = () => {
);
};

export default Client;
export default ApiKeyPage;
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import UserAvatar from '@/features/User/UserAvatar';
import { useUserStore } from '@/store/user';
import { authSelectors, userProfileSelectors } from '@/store/user/selectors';

import SSOProvidersList from './features/SSOProvidersList';
import SSOProvidersList from '../features/SSOProvidersList';

const Client = memo<{ mobile?: boolean }>(({ mobile }) => {
const ProfilePage = memo<{ mobile?: boolean }>(({ mobile }) => {
const [isLoginWithNextAuth, isLogin] = useUserStore((s) => [
authSelectors.isLoginWithNextAuth(s),
authSelectors.isLogin(s),
Expand Down Expand Up @@ -83,4 +83,4 @@ const Client = memo<{ mobile?: boolean }>(({ mobile }) => {
);
});

export default Client;
export default ProfilePage;
Loading
Loading