Skip to content

Commit

Permalink
Feat: Add ProfileSetting page #3221 (#3588)
Browse files Browse the repository at this point in the history
### What problem does this PR solve?

Feat: Add ProfileSetting page  #3221
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
  • Loading branch information
cike8899 authored Nov 22, 2024
1 parent ee7fd71 commit ee33bf7
Show file tree
Hide file tree
Showing 15 changed files with 334 additions and 28 deletions.
2 changes: 1 addition & 1 deletion web/src/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const buttonVariants = cva(
destructive:
'bg-destructive text-destructive-foreground hover:bg-destructive/90',
outline:
'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
'border border-colors-outline-sentiment-primary bg-background hover:bg-accent hover:text-accent-foreground',
secondary:
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
Expand Down
21 changes: 13 additions & 8 deletions web/src/constants/setting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,19 @@ export enum UserSettingRouteKey {
Logout = 'logout',
}

export const UserSettingRouteMap = {
[UserSettingRouteKey.Profile]: 'Profile',
[UserSettingRouteKey.Password]: 'Password',
[UserSettingRouteKey.Model]: 'Model Providers',
[UserSettingRouteKey.System]: 'System Version',
[UserSettingRouteKey.Team]: 'Team',
[UserSettingRouteKey.Logout]: 'Log out',
};
export const ProfileSettingBaseKey = 'profile-setting';

export enum ProfileSettingRouteKey {
Profile = 'profile',
Plan = 'plan',
Model = 'model',
System = 'system',
Api = 'api',
Team = 'team',
Prompt = 'prompt',
Chunk = 'chunk',
Logout = 'logout',
}

// Please lowercase the file name
export const IconMap = {
Expand Down
48 changes: 34 additions & 14 deletions web/src/pages/home/applications.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
import { Segmented, SegmentedValue } from '@/components/ui/segmented ';
import { ChevronRight, Cpu, MessageSquare, Search } from 'lucide-react';
import { useMemo, useState } from 'react';

const applications = [
{
Expand Down Expand Up @@ -34,24 +36,42 @@ const applications = [
];

export function Applications() {
const [val, setVal] = useState('all');
const options = useMemo(() => {
return [
{
label: 'All',
value: 'all',
},
{
label: 'Chat',
value: 'chat',
},
{
label: 'Search',
value: 'search',
},
{
label: 'Agent',
value: 'agent',
},
];
}, []);

const handleChange = (path: SegmentedValue) => {
setVal(path as string);
};

return (
<section className="mt-12">
<div className="flex justify-between items-center mb-6">
<h2 className="text-2xl font-bold">Applications</h2>
<div className="flex bg-colors-background-inverse-standard rounded-lg p-1">
<Button variant="default" size="sm">
All
</Button>
<Button variant="ghost" size="sm">
Chat
</Button>
<Button variant="ghost" size="sm">
Search
</Button>
<Button variant="ghost" size="sm">
Agents
</Button>
</div>
<Segmented
options={options}
value={val}
onChange={handleChange}
className="bg-colors-background-inverse-standard"
></Segmented>
</div>
<div className="grid grid-cols-4 gap-6">
{[...Array(12)].map((_, i) => {
Expand Down
8 changes: 4 additions & 4 deletions web/src/pages/home/datasets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,31 @@ const datasets = [
files: '1,242 files',
size: '152 MB',
created: '12.02.2024',
image: '/image-3.png',
image: 'https://github.com/shadcn.png',
},
{
id: 2,
title: 'HR knowledge base',
files: '1,242 files',
size: '152 MB',
created: '12.02.2024',
image: '/image.png',
image: 'https://github.com/shadcn.png',
},
{
id: 3,
title: 'IT knowledge base',
files: '1,242 files',
size: '152 MB',
created: '12.02.2024',
image: '/rectangle-86.png',
image: 'https://github.com/shadcn.png',
},
{
id: 4,
title: 'Legal knowledge base',
files: '1,242 files',
size: '152 MB',
created: '12.02.2024',
image: '/image-2.png',
image: 'https://github.com/shadcn.png',
},
];

Expand Down
2 changes: 1 addition & 1 deletion web/src/pages/home/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export function HomeHeader() {
options={options}
value={currentPath}
onChange={handleChange}
className="bg-backgroundInverseStandard text-backgroundInverseStandard-foreground"
className="bg-colors-background-inverse-standard text-backgroundInverseStandard-foreground"
></Segmented>
</div>
<div className="flex items-center gap-4">
Expand Down
20 changes: 20 additions & 0 deletions web/src/pages/profile-setting/hooks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ProfileSettingRouteKey } from '@/constants/setting';
import { useSecondPathName } from '@/hooks/route-hook';

export const useGetPageTitle = (): string => {
const pathName = useSecondPathName();

const LabelMap = {
[ProfileSettingRouteKey.Profile]: 'User profile',
[ProfileSettingRouteKey.Plan]: 'Plan & balance',
[ProfileSettingRouteKey.Model]: 'Model management',
[ProfileSettingRouteKey.System]: 'System',
[ProfileSettingRouteKey.Api]: 'Api',
[ProfileSettingRouteKey.Team]: 'Team management',
[ProfileSettingRouteKey.Prompt]: 'Prompt management',
[ProfileSettingRouteKey.Chunk]: 'Chunk method',
[ProfileSettingRouteKey.Logout]: 'Logout',
};

return LabelMap[pathName as ProfileSettingRouteKey];
};
34 changes: 34 additions & 0 deletions web/src/pages/profile-setting/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Button } from '@/components/ui/button';
import { ArrowLeft } from 'lucide-react';
import { Outlet } from 'umi';
import { useGetPageTitle } from './hooks';
import { SideBar } from './sidebar';

export default function ProfileSetting() {
const title = useGetPageTitle();
return (
<div className="flex flex-col w-full h-screen bg-background text-foreground">
<header className="flex items-center border-b">
<div className="flex items-center border-r p-1.5">
<Button variant="ghost" size="icon">
<ArrowLeft className="w-5 h-5" />
</Button>
</div>
<div className="p-4">
<h1 className="text-2xl font-semibold tracking-tight">
Profile & settings
</h1>
</div>
</header>

<div className="flex flex-1 bg-muted/50">
<SideBar></SideBar>

<main className="flex-1 p-10">
<h1 className="text-3xl font-bold mb-6"> {title}</h1>
<Outlet></Outlet>
</main>
</div>
</div>
);
}
3 changes: 3 additions & 0 deletions web/src/pages/profile-setting/plan/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Plan() {
return <div>plan</div>;
}
72 changes: 72 additions & 0 deletions web/src/pages/profile-setting/profile/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';

export default function Profile() {
return (
<section>
<Avatar className="w-[120px] h-[120px] mb-6">
<AvatarImage
src={
'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg'
}
alt="Profile"
/>
<AvatarFallback>YW</AvatarFallback>
</Avatar>

<div className="space-y-6 max-w-[600px]">
<div className="space-y-2">
<label className="text-sm text-muted-foreground">User name</label>
<Input
defaultValue="yifanwu92"
className="bg-colors-background-inverse-weak"
/>
</div>

<div className="space-y-2">
<label className="text-sm text-muted-foreground">Email</label>
<Input
defaultValue="[email protected]"
className="bg-colors-background-inverse-weak"
/>
</div>

<div className="space-y-2">
<label className="text-sm text-muted-foreground">Language</label>
<Select defaultValue="english">
<SelectTrigger className="bg-colors-background-inverse-weak">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="english">English</SelectItem>
</SelectContent>
</Select>
</div>

<div className="space-y-2">
<label className="text-sm text-muted-foreground">Timezone</label>
<Select defaultValue="utc9">
<SelectTrigger className="bg-colors-background-inverse-weak">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="utc9">UTC+9 Asia/Shanghai</SelectItem>
</SelectContent>
</Select>
</div>

<Button variant="outline" className="mt-4">
Change password
</Button>
</div>
</section>
);
}
25 changes: 25 additions & 0 deletions web/src/pages/profile-setting/sidebar/hooks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {
ProfileSettingBaseKey,
ProfileSettingRouteKey,
} from '@/constants/setting';
import { useLogout } from '@/hooks/login-hooks';
import { useCallback } from 'react';
import { useNavigate } from 'umi';

export const useHandleMenuClick = () => {
const navigate = useNavigate();
const { logout } = useLogout();

const handleMenuClick = useCallback(
(key: ProfileSettingRouteKey) => () => {
if (key === ProfileSettingRouteKey.Logout) {
logout();
} else {
navigate(`/${ProfileSettingBaseKey}/${key}`);
}
},
[logout, navigate],
);

return { handleMenuClick };
};
92 changes: 92 additions & 0 deletions web/src/pages/profile-setting/sidebar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { Switch } from '@/components/ui/switch';
import { ProfileSettingRouteKey } from '@/constants/setting';
import { useSecondPathName } from '@/hooks/route-hook';
import { cn } from '@/lib/utils';
import {
AlignEndVertical,
Banknote,
Box,
FileCog,
LayoutGrid,
LogOut,
User,
} from 'lucide-react';
import { useHandleMenuClick } from './hooks';

const menuItems = [
{
section: 'Account & collaboration',
items: [
{ icon: User, label: 'Profile', key: ProfileSettingRouteKey.Profile },
{ icon: LayoutGrid, label: 'Team', key: ProfileSettingRouteKey.Team },
{ icon: Banknote, label: 'Plan', key: ProfileSettingRouteKey.Plan },
],
},
{
section: 'System configurations',
items: [
{
icon: Box,
label: 'Model management',
key: ProfileSettingRouteKey.Model,
},
{
icon: FileCog,
label: 'Prompt management',
key: ProfileSettingRouteKey.Prompt,
},
{
icon: AlignEndVertical,
label: 'Chunking method',
key: ProfileSettingRouteKey.Chunk,
},
],
},
];

export function SideBar() {
const pathName = useSecondPathName();
const { handleMenuClick } = useHandleMenuClick();

return (
<aside className="w-[303px] bg-background border-r">
{menuItems.map((section, idx) => (
<div key={idx}>
<h2 className="p-6 text-sm font-semibold">{section.section}</h2>
{section.items.map((item, itemIdx) => {
const active = pathName === item.key;
return (
<Button
key={itemIdx}
variant={active ? 'secondary' : 'ghost'}
className={cn('w-full justify-start gap-2.5 p-6 relative')}
onClick={handleMenuClick(item.key)}
>
<item.icon className="w-6 h-6" />
<span>{item.label}</span>
{active && (
<div className="absolute right-0 w-[5px] h-[66px] bg-primary rounded-l-xl shadow-[0_0_5.94px_#7561ff,0_0_11.88px_#7561ff,0_0_41.58px_#7561ff,0_0_83.16px_#7561ff,0_0_142.56px_#7561ff,0_0_249.48px_#7561ff]" />
)}
</Button>
);
})}
</div>
))}

<div className="p-6 mt-auto border-t">
<div className="flex items-center gap-2 mb-6">
<Switch id="dark-mode" />
<Label htmlFor="dark-mode" className="text-sm">
Dark
</Label>
</div>
<Button variant="outline" className="w-full gap-3">
<LogOut className="w-6 h-6" />
Logout
</Button>
</div>
</aside>
);
}
Loading

0 comments on commit ee33bf7

Please sign in to comment.