change(ui): projects revamp - project menu improvements
This commit is contained in:
parent
1c7c3a776d
commit
99b0ca4af5
3 changed files with 71 additions and 63 deletions
|
|
@ -1,85 +1,92 @@
|
|||
import React from 'react';
|
||||
import { Avatar, Input, Menu, Progress } from 'antd';
|
||||
import { Avatar, Input, Menu, MenuProps, Progress } from 'antd';
|
||||
import { useStore } from '@/mstore';
|
||||
import Project from '@/mstore/types/project';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { AppWindowMac, Smartphone } from 'lucide-react';
|
||||
|
||||
function ProjectList() {
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
|
||||
const ProjectList: React.FC = () => {
|
||||
const { projectsStore } = useStore();
|
||||
const list = projectsStore.list;
|
||||
const [search, setSearch] = React.useState('');
|
||||
const config = projectsStore.config;
|
||||
|
||||
const onSearch = (value: string) => {
|
||||
setSearch(value);
|
||||
const filteredProjects = projectsStore.list.filter((project: Project) =>
|
||||
project.name.toLowerCase().includes(search.toLowerCase())
|
||||
);
|
||||
|
||||
const handleSearch = (value: string) => setSearch(value);
|
||||
|
||||
const onClick: MenuProps['onClick'] = (e) => {
|
||||
const pid = parseInt(e.key as string);
|
||||
projectsStore.setConfigProject(pid);
|
||||
};
|
||||
|
||||
const onProjectClick = (project: Project) => {
|
||||
projectsStore.setConfigProject(project.projectId);
|
||||
};
|
||||
const menuItems: MenuItem[] = filteredProjects.map((project) => ({
|
||||
key: project.id + '',
|
||||
label: project.name,
|
||||
icon: (
|
||||
<ProjectIconWithProgress
|
||||
platform={project.platform}
|
||||
progress={project.sampleRate}
|
||||
/>
|
||||
)
|
||||
}));
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col gap-4">
|
||||
<div className="px-4 mt-4">
|
||||
<Input.Search
|
||||
placeholder="Search"
|
||||
onSearch={onSearch}
|
||||
onClear={() => setSearch('')}
|
||||
placeholder="Search projects"
|
||||
onSearch={handleSearch}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
allowClear
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
height: 'calc(100vh - 250px)'
|
||||
}}
|
||||
className="overflow-y-auto"
|
||||
style={{ height: 'calc(100vh - 250px)' }}
|
||||
>
|
||||
<Menu
|
||||
mode="inline"
|
||||
selectedKeys={[config.pid + '']}
|
||||
className="w-full ml-0 pl-0 !bg-white !border-r-0"
|
||||
items={list.filter((item: Project) => item.name.toLowerCase().includes(search.toLowerCase())).map((project) => ({
|
||||
key: project.id,
|
||||
label: project.name,
|
||||
onClick: () => onProjectClick(project),
|
||||
icon: <ProjectIconWithProgress platform={project.platform} progress={project.sampleRate} />
|
||||
})) as any}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default observer(ProjectList);
|
||||
|
||||
|
||||
const ProjectIconWithProgress: React.FC<{
|
||||
platform: string; progress: number
|
||||
}> = ({ platform, progress }) => {
|
||||
return (
|
||||
<div className="relative flex items-center justify-center mr-2 leading-none">
|
||||
<Progress
|
||||
type="circle"
|
||||
percent={progress}
|
||||
size={28}
|
||||
format={() => ''}
|
||||
strokeWidth={4}
|
||||
strokeColor="#23959a"
|
||||
/>
|
||||
<div className="absolute">
|
||||
<Avatar
|
||||
className="bg-tealx-light"
|
||||
size={26}
|
||||
icon={
|
||||
platform === 'web' ? (
|
||||
<AppWindowMac size={16} color="teal" />
|
||||
) : (
|
||||
<Smartphone size={16} color="teal" />
|
||||
)
|
||||
}
|
||||
onClick={onClick}
|
||||
selectedKeys={[String(projectsStore.config.pid)]}
|
||||
className="w-full !bg-white !border-0"
|
||||
inlineIndent={11}
|
||||
items={menuItems}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(ProjectList);
|
||||
|
||||
const ProjectIconWithProgress: React.FC<{
|
||||
platform: string;
|
||||
progress: number;
|
||||
}> = ({ platform, progress }) => (
|
||||
<div className="relative flex items-center justify-center mr-2 leading-none">
|
||||
<Progress
|
||||
type="circle"
|
||||
percent={progress}
|
||||
size={28}
|
||||
format={() => ''}
|
||||
strokeWidth={4}
|
||||
strokeColor="#23959a"
|
||||
/>
|
||||
<div className="absolute">
|
||||
<Avatar
|
||||
className="bg-tealx-light"
|
||||
size={26}
|
||||
icon={
|
||||
platform === 'web' ? (
|
||||
<AppWindowMac size={16} color="teal" />
|
||||
) : (
|
||||
<Smartphone size={16} color="teal" />
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -47,10 +47,10 @@ function Projects() {
|
|||
<Card
|
||||
style={{ height: 'calc(100vh - 130px)' }}
|
||||
classNames={{
|
||||
header: '!border-b',
|
||||
header: '!border-b !px-4',
|
||||
body: '!p-0 !border-t'
|
||||
}}
|
||||
title="Projects"
|
||||
title={<Typography.Title level={4} className="!m-0">Projects</Typography.Title>}
|
||||
extra={[
|
||||
<Button onClick={createProject} icon={<PlusIcon size={18} />}>
|
||||
Create Project
|
||||
|
|
@ -58,7 +58,7 @@ function Projects() {
|
|||
]}
|
||||
>
|
||||
<Layout>
|
||||
<Layout.Sider width={300} trigger={null}
|
||||
<Layout.Sider width={260} trigger={null}
|
||||
className="!bg-white border-r">
|
||||
<ProjectList />
|
||||
</Layout.Sider>
|
||||
|
|
|
|||
|
|
@ -46,13 +46,13 @@ const customTheme: ThemeConfig = {
|
|||
itemSelectedColor: colors['teal'],
|
||||
|
||||
itemMarginBlock: 0,
|
||||
itemPaddingInline: 50,
|
||||
iconMarginInlineEnd: 14,
|
||||
// itemPaddingInline: 50,
|
||||
// iconMarginInlineEnd: 14,
|
||||
collapsedWidth: 180
|
||||
},
|
||||
Button: {
|
||||
colorPrimary: colors.teal
|
||||
}
|
||||
},
|
||||
},
|
||||
token: {
|
||||
colorPrimary: colors.teal,
|
||||
|
|
@ -64,7 +64,8 @@ const customTheme: ThemeConfig = {
|
|||
|
||||
borderRadius: 4,
|
||||
fontSize: 14,
|
||||
fontFamily: '\'Roboto\', \'ArialMT\', \'Arial\''
|
||||
fontFamily: '\'Roboto\', \'ArialMT\', \'Arial\'',
|
||||
fontWeightStrong: 400,
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue