Skip to content

Commit

Permalink
refactor(web): extract sidebar as component
Browse files Browse the repository at this point in the history
  • Loading branch information
edwardzjl committed Dec 30, 2024
1 parent 6ec9ff1 commit ee847c9
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 132 deletions.
75 changes: 75 additions & 0 deletions web/src/routes/root/Sidebar/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import styles from "./index.module.css";

import { useContext } from "react";
import { Link, NavLink } from "react-router-dom";
import PropTypes from "prop-types";

import AddOutlinedIcon from "@mui/icons-material/AddOutlined";
import GitHubIcon from "@mui/icons-material/GitHub";
import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
import MailOutlineIcon from "@mui/icons-material/MailOutline";

import { ConversationContext } from "@/contexts/conversation";

import ChatTab from "../ChatTab";


const Sidebar = ({onShareClick, onDeleteClick}) => {
const { groupedConvs } = useContext(ConversationContext);

return (
<aside className={styles.sidebar}>
<Link className={styles.sidebarButton} to="/">
<AddOutlinedIcon />
New Chat
</Link>
<nav className={styles.convList}>
{groupedConvs && Object.entries(groupedConvs)
.filter(([, convs]) => convs && convs.length > 0) // Filter out empty lists
.flatMap(([grp, convs]) => (
[
<div key={grp}>
<div className={styles.sidebarDateGroup}>{grp}</div>
<ul>
{convs.map((conv) => (
<li key={conv.id}>
<NavLink
to={`conversations/${conv.id}`}
className={`${styles.sidebarButton} ${({ isActive, isPending }) => isActive ? "active" : isPending ? "pending" : ""}`}
>
{({ isActive }) => (
<ChatTab chat={conv} isActive={isActive} onShareClick={onShareClick} onDeleteClick={onDeleteClick} />
)}
</NavLink>
</li>
))}
</ul>
</div>
]
))}
</nav>
<hr className={styles.sidebarBottom} />
<div className={styles.sidebarBottomGroup}>
<div className={styles.sidebarBottomGroupItem}>
<InfoOutlinedIcon />
</div>
<div className={styles.sidebarBottomGroupItem}>
<a href="https://github.com/edwardzjl/chatbot" target="_blank" rel="noreferrer"> <GitHubIcon /> </a>
</div>
<div className={styles.sidebarBottomGroupItem}>
<a href="mailto:jameszhou2108@hotmail.com">
<MailOutlineIcon />
</a>
</div>
</div>
</aside>
);
};

Sidebar.propTypes = {
onShareClick: PropTypes.func.isRequired,
onDeleteClick: PropTypes.func.isRequired,
};


export default Sidebar;
77 changes: 77 additions & 0 deletions web/src/routes/root/Sidebar/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
.sidebar {
width: 260px;
padding: 10px;
border: 1px solid rgba(255, 255, 255, .2);
background-color: var(--bg-primary);
display: flex;
flex-direction: column;
}

.sidebar ul {
list-style-type: none;
margin: 0;
padding: 0;
}

.sidebar li {
list-style: none;
width: 100%;
}

.sidebar a {
color: unset;
text-decoration: none;
}

.convList {
display: flex;
height: 100%;
flex-direction: column;
overflow: auto;
scrollbar-color: var(--border-color) transparent;
scrollbar-width: thin;
}

.sidebarDateGroup {
color: var(--text-3);
text-align: start;
margin: 10px;
margin-top: 20px;
}

.sidebarButton {
height: 2rem;
margin: 2px;
padding: 3px;
background-color: var(--bg-primary);
color: var(--text-primary);
border: none;
border-radius: 5px;
transition: ease 0.25s all;
display: flex;
flex-direction: row;
align-items: center;
}

.sidemenu-button:hover {
background-color: var(--bg-secondary);
}

.sidemenu-button.active {
background-color: var(--bg-secondary);
}

.sidebarBottom {
margin-top: auto;
width: 90%;
border: 1px solid var(--border-color);
}

.sidebarBottomGroup {
margin: 1rem;
display: flex;
}

.sidebarBottomGroupItem {
margin: 0.5rem;
}
78 changes: 0 additions & 78 deletions web/src/routes/root/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -90,84 +90,6 @@
color: #61dafb;
}

.sidemenu {
width: 260px;
padding: 10px;
border: 1px solid rgba(255, 255, 255, .2);
background-color: var(--bg-primary);
display: flex;
flex-direction: column;
}

.sidemenu ul {
list-style-type: none;
margin: 0;
padding: 0;
}

.sidemenu li {
list-style: none;
width: 100%;
}

.sidemenu a {
color: unset;
text-decoration: none;
}

.conv-list {
display: flex;
height: 100%;
flex-direction: column;
overflow: auto;
scrollbar-color: var(--border-color) transparent;
scrollbar-width: thin;
}

.sidemenu-date-group {
color: var(--text-3);
text-align: start;
margin: 10px;
margin-top: 20px;
}

.sidemenu-button {
height: 2rem;
margin: 2px;
padding: 3px;
background-color: var(--bg-primary);
color: var(--text-primary);
border: none;
border-radius: 5px;
transition: ease 0.25s all;
display: flex;
flex-direction: row;
align-items: center;
}

.sidemenu-button:hover {
background-color: var(--bg-secondary);
}

.sidemenu-button.active {
background-color: var(--bg-secondary);
}

.sidemenu-bottom {
margin-top: auto;
width: 90%;
border: 1px solid var(--border-color);
}

.sidemenu-bottom-group {
margin: 1rem;
display: flex;
}

.sidemenu-bottom-group-items {
margin: 0.5rem;
}

.del-dialog {
width: 25vw;
color: var(--text-primary);
Expand Down
59 changes: 5 additions & 54 deletions web/src/routes/root/index.jsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
import "./index.css";

import { forwardRef, useContext, useEffect, useRef, useState } from "react";
import { Link, NavLink, Outlet, redirect, useNavigate } from "react-router-dom";
import { Outlet, redirect, useNavigate } from "react-router-dom";

import Snackbar from "@mui/material/Snackbar";
import MuiAlert from "@mui/material/Alert";
import Tooltip from "@mui/material/Tooltip";

import AddOutlinedIcon from "@mui/icons-material/AddOutlined";
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
import GitHubIcon from "@mui/icons-material/GitHub";
import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
import MailOutlineIcon from "@mui/icons-material/MailOutline";

import { SnackbarContext } from "@/contexts/snackbar";
import { ThemeContext } from "@/contexts/theme";
import { ConversationContext } from "@/contexts/conversation";
import { MessageContext } from "@/contexts/message";
import { WebsocketContext } from "@/contexts/websocket";

import ChatTab from "./ChatTab";

import Sidebar from "./Sidebar";

const Alert = forwardRef(function Alert(props, ref) {
return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />;
Expand All @@ -35,7 +30,7 @@ export async function action({ request }) {
}

const Root = () => {
const { groupedConvs, dispatch: dispatchConv } = useContext(ConversationContext);
const { dispatch: dispatchConv } = useContext(ConversationContext);

const { theme } = useContext(ThemeContext);
const { snackbar, setSnackbar } = useContext(SnackbarContext);
Expand Down Expand Up @@ -156,51 +151,8 @@ const Root = () => {

return (
<div className={`App theme-${theme}`}>
<aside className="sidemenu">
<Link className="sidemenu-button" to="/">
<AddOutlinedIcon />
New Chat
</Link>
<nav className="conv-list">
{groupedConvs && Object.entries(groupedConvs)
.filter(([, convs]) => convs && convs.length > 0) // Filter out empty lists
.flatMap(([grp, convs]) => (
[
<div key={grp}>
<div className="sidemenu-date-group">{grp}</div>
<ul>
{convs.map((conv) => (
<li key={conv.id}>
<NavLink
to={`conversations/${conv.id}`}
className={`sidemenu-button ${({ isActive, isPending }) => isActive ? "active" : isPending ? "pending" : ""}`}
>
{({ isActive }) => (
<ChatTab chat={conv} isActive={isActive} onShareClick={onShareClick} onDeleteClick={onDeleteClick} />
)}
</NavLink>
</li>
))}
</ul>
</div>
]
))}
</nav>
<hr className="sidemenu-bottom" />
<div className="sidemenu-bottom-group">
<div className="sidemenu-bottom-group-items">
<InfoOutlinedIcon />
</div>
<div className="sidemenu-bottom-group-items">
<a href="https://github.com/edwardzjl/chatbot" target="_blank" rel="noreferrer"> <GitHubIcon /> </a>
</div>
<div className="sidemenu-bottom-group-items">
<a href="mailto:jameszhou2108@hotmail.com">
<MailOutlineIcon />
</a>
</div>
</div>
</aside>
<Sidebar onShareClick={onShareClick} onDeleteClick={onDeleteClick} />
<Outlet />
<dialog
id="share-conv-dialog"
className="del-dialog"
Expand Down Expand Up @@ -248,7 +200,6 @@ const Root = () => {
<button onClick={() => delDialogRef.current?.close()}>Cancel</button>
</div>
</dialog>
<Outlet />
<Snackbar
open={snackbar.open}
autoHideDuration={3000}
Expand Down

0 comments on commit ee847c9

Please sign in to comment.