Skip to content

Commit

Permalink
add: folder tree
Browse files Browse the repository at this point in the history
  • Loading branch information
majkshkurti committed Sep 22, 2023
1 parent 7d82589 commit 4a86067
Show file tree
Hide file tree
Showing 14 changed files with 487 additions and 94 deletions.
134 changes: 76 additions & 58 deletions apps/web/app/[lng]/(dashboard)/projects/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ import {
Box,
Button,
Container,
Divider,
Grid,
IconButton,
InputBase,
Paper,
Typography,
useTheme,
} from "@mui/material";
import { ICON_NAME, Icon } from "@p4b/ui/components/Icon";
import GridViewIcon from "@mui/icons-material/GridView";
import FormatListBulletedIcon from "@mui/icons-material/FormatListBulleted";
import { useState } from "react";
import { useProjects } from "@/lib/api/projects";
import TileGrid from "@/components/dashboard/common/TileGrid";
import FoldersTreeView from "@/components/dashboard/common/FoldersTreeView";

const Projects = () => {
const {
Expand All @@ -28,10 +32,12 @@ const Projects = () => {
const newView = view === "list" ? "grid" : "list";
setView(newView);
};
const theme = useTheme();

return (
<Container sx={{ py: 10, px: 10 }} maxWidth="xl">
{/* {Header} */}

<Box
sx={{
display: "flex",
Expand All @@ -51,65 +57,77 @@ const Projects = () => {
New project
</Button>
</Box>
{/* Search bar */}
<Box
sx={{
display: "flex",
justifyContent: "start",
alignItems: "center",
mt: 2,
mb: 8,
}}
>
<Paper
component="form"
elevation={0}
sx={{
py: 1,
px: 4,
display: "flex",
alignItems: "center",
width: "100%",
}}
>
<Icon
iconName={ICON_NAME.SEARCH}
fontSize="small"
style={{ fontSize: 12 }}
/>
<InputBase
sx={{ ml: 2, flex: 1 }}
placeholder="Search Projects"
inputProps={{ "aria-label": "search projects" }}
/>
</Paper>
<IconButton
sx={{
ml: 2,
p: 2,
borderRadius: 1,
}}
>
<Icon iconName={ICON_NAME.FILTER} fontSize="small" />
</IconButton>
<IconButton
onClick={handleViewToggle}
sx={{
mx: 2,
p: 2,
borderRadius: 1,
}}
>
{view === "list" ? <GridViewIcon /> : <FormatListBulletedIcon />}
</IconButton>
</Box>
<Grid container justifyContent="space-between" spacing={4}>
<Grid item xs={12}>
<Box
sx={{
display: "flex",
justifyContent: "start",
alignItems: "center",
mt: 2,
}}
>
<Paper
component="form"
elevation={3}
sx={{
py: 1,
px: 4,
display: "flex",
alignItems: "center",
width: "100%",
}}
>
{/* Search bar */}
<Icon iconName={ICON_NAME.SEARCH} style={{ fontSize: 17 }} />
<InputBase
sx={{ ml: 3, flex: 1 }}
placeholder="Search Projects"
inputProps={{ "aria-label": "search projects" }}
/>
<Divider orientation="vertical" flexItem />
<IconButton
sx={{
mx: 2,
p: 2,
borderRadius: 1,
}}
>
<Icon iconName={ICON_NAME.FILTER} fontSize="small" />
</IconButton>
<Divider orientation="vertical" flexItem />

<TileGrid
view={view}
items={projects?.items ?? []}
isLoading={isProjectLoading}
type="project"
/>
<IconButton
onClick={handleViewToggle}
sx={{
ml: 2,
p: 2,
borderRadius: 1,
}}
>
{view === "list" ? (
<GridViewIcon />
) : (
<FormatListBulletedIcon />
)}
</IconButton>
</Paper>
</Box>
</Grid>
<Grid item xs={3}>
<Paper elevation={3} sx={{backgroundImage: 'none'}}>
<FoldersTreeView />
</Paper>
</Grid>
<Grid item xs={9}>
<TileGrid
view={view}
items={projects?.items ?? []}
isLoading={isProjectLoading}
type="project"
/>
</Grid>
</Grid>
</Container>
);
};
Expand Down
4 changes: 2 additions & 2 deletions apps/web/components/@mui/ThemeRegistry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export default function ThemeRegistry({
}: {
children: React.ReactNode;
}) {
let theme = "dark";
let theme = "light";
if (typeof window !== "undefined") {
theme = localStorage.getItem("theme") || "dark";
theme = localStorage.getItem("theme") || "light";
}

const [mode, setMode] = React.useState<"light" | "dark">(
Expand Down
156 changes: 156 additions & 0 deletions apps/web/components/common/TreeViewItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import * as React from "react";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import clsx from "clsx";

import type {
TreeItemContentProps,
TreeItemProps,
} from "@mui/x-tree-view/TreeItem";
import {
TreeItem,
treeItemClasses,
useTreeItem,
} from "@mui/x-tree-view/TreeItem";
import { useTheme } from "@mui/material";

type StyledTreeItemProps = TreeItemProps & {
labelIcon: JSX.Element;
labelInfo?: string;
labelText: string;
actionElement?: JSX.Element;
};

const CustomContent = React.forwardRef(function CustomContent(
props: TreeItemContentProps,
ref,
) {
const {
classes,
className,
label,
nodeId,
icon: iconProp,
expansionIcon,
displayIcon,
} = props;

const {
disabled,
expanded,
selected,
focused,
handleExpansion,
handleSelection,
preventSelection,
} = useTreeItem(nodeId);

const icon = iconProp || expansionIcon || displayIcon;

const handleMouseDown = (
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
) => {
preventSelection(event);
};

const handleExpansionClick = (
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
) => {
handleExpansion(event);
};

const handleSelectionClick = (
event: React.MouseEvent<HTMLDivElement, MouseEvent>,
) => {
handleSelection(event);
};

return (
<div
className={clsx(className, classes.root, {
[classes.expanded]: expanded,
[classes.selected]: selected,
[classes.focused]: focused,
[classes.disabled]: disabled,
})}
onMouseDown={handleMouseDown}
ref={ref as React.Ref<HTMLDivElement>}
>
<div onClick={handleExpansionClick} className={classes.iconContainer}>
{icon}
</div>
<Box
component="div"
className={classes.label}
onClick={handleSelectionClick}
sx={{
display: "flex",
alignItems: "center",
py: 2,
pr: 1,
}}
>
{label}
</Box>
</div>
);
});

const StyledTreeItem = React.forwardRef(function StyledTreeItem(
props: StyledTreeItemProps,
ref: React.Ref<HTMLLIElement>,
) {
const { labelIcon, labelInfo, labelText, actionElement, ...other } = props;
const theme = useTheme();
return (
<TreeItem
ContentComponent={CustomContent}
sx={{
[`& .${treeItemClasses.content}`]: {
"&.Mui-selected, &.Mui-selected.Mui-focused": {
fontWeight: 700,
color: theme.palette.primary.main,
},
[`& .${treeItemClasses.label}`]: {
fontWeight: "inherit",
color: "inherit",
},
"& .MuiTreeItem-iconContainer": {
mr: 3,
ml: 1,
},
},
[`& .${treeItemClasses.group}`]: {
marginLeft: 0,
[`& .${treeItemClasses.content}`]: {
paddingLeft: 6,
},
},
}}
label={
<>
<Box
color="inherit"
sx={{ mr: 4, py: 2, display: "inherit", color: "inherit" }}
>
{labelIcon}
</Box>
<Typography
variant="body1"
sx={{ fontWeight: "inherit", flexGrow: 1, color: "inherit" }}
>
{labelText}
</Typography>
<Typography variant="caption" color="inherit">
{labelInfo}
</Typography>
{actionElement}
</>
}
{...other}
ref={ref}
/>
);
});

export default StyledTreeItem;
Loading

0 comments on commit 4a86067

Please sign in to comment.