Skip to content

Commit

Permalink
✨ (sidebar): introducing right sidebar from same component (#126)
Browse files Browse the repository at this point in the history
  • Loading branch information
AbdelruhmanSamy authored Dec 15, 2024
1 parent 61e9867 commit b8abb66
Show file tree
Hide file tree
Showing 16 changed files with 207 additions and 109 deletions.
24 changes: 19 additions & 5 deletions app/src/components/AppLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ import styled from "styled-components";
import Main from "./Main";
import SideBar from "./side-bar/SideBar";
import { DESKTOP_VIEW, MOBILE_VIEW } from "@constants";
import { useState } from "react";

const StyledApp = styled.div<{ $isChatOpen: boolean }>`
const StyledApp = styled.div<{
$isChatOpen: boolean;
$isRightSideBarOpen: boolean;
}>`
@media ${MOBILE_VIEW} {
& > main {
display: ${({ $isChatOpen }) => ($isChatOpen ? "contents" : "none")};
Expand All @@ -17,7 +21,10 @@ const StyledApp = styled.div<{ $isChatOpen: boolean }>`
@media ${DESKTOP_VIEW} {
display: grid;
grid-template-columns: minmax(20rem, 2.5fr) 5fr;
grid-template-columns: ${({ $isRightSideBarOpen }) =>
$isRightSideBarOpen ? "1.5fr 3fr 1.5fr" : "1.5fr 4.5fr"};
overflow-x: hidden;
& > main {
display: block;
Expand All @@ -34,12 +41,19 @@ function AppLayout() {

const isChatOpen = !!chatId;

const [showRightSideBar, setShowRightSideBar] = useState<boolean>(false);

return (
<StyledApp $isChatOpen={isChatOpen} data-testid="app-layout">
<SideBar />
<StyledApp
$isChatOpen={isChatOpen}
data-testid="app-layout"
$isRightSideBarOpen={showRightSideBar}
>
<SideBar type="left" />
<Main>
<Outlet />
<Outlet context={{ setShowRightSideBar, showRightSideBar }} />
</Main>
{showRightSideBar && <SideBar type="right" />}
</StyledApp>
);
}
Expand Down
10 changes: 8 additions & 2 deletions app/src/components/BackArrow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import styled from "styled-components";
import { getIcon } from "@data/icons";
import { useAppDispatch, useAppSelector } from "@hooks/useGlobalState";
import { updateSideBarView } from "@state/side-bar/sideBar";
import { useSidebarType } from "./side-bar/SideBarContext";

const StyledArrow = styled.div`
width: 30px;
Expand All @@ -20,14 +21,19 @@ const StyledArrow = styled.div`

function BackArrow() {
const dispatch = useAppDispatch();
const { backView } = useAppSelector((state) => state.sideBarData);
const type = useSidebarType();
const { backView } = useAppSelector((state) =>
type === "left"
? state.sideBarData.leftSideBar
: state.sideBarData.rightSideBar
);

return (
<StyledArrow
data-testid="back-arrow-icon"
onClick={() =>
backView !== undefined &&
dispatch(updateSideBarView({ redirect: backView }))
dispatch(updateSideBarView({ redirect: backView, data: { type } }))
}
>
{getIcon("BackArrow")}
Expand Down
5 changes: 3 additions & 2 deletions app/src/components/UsersList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { updateSideBarView } from "@state/side-bar/sideBar";

import { useAllUsers } from "@features/groups/hooks/useAllUsers";
import { useUser } from "@features/authentication/login/hooks/useUser";
import { useSidebarType } from "./side-bar/SideBarContext";

const Container = styled.div`
width: 100%;
Expand Down Expand Up @@ -39,13 +40,13 @@ function UsersList({ type }: { type: "channel" | "group" }) {
const { user: currentUser, isPending: isPendingCurrentUser } = useUser();
const [searchQuery, setSearchQuery] = useState<string>("");
const dispatch = useAppDispatch();

const sideBarType = useSidebarType();
if (isPendenigAllUsers || isPendingCurrentUser) return null;

function handleClick() {
const redirect =
type === "channel" ? sideBarPages.NEW_CHANNEL : sideBarPages.NEW_GROUP;
dispatch(updateSideBarView({ redirect }));
dispatch(updateSideBarView({ redirect, data: { type: sideBarType } }));
}

const filteredUsers = users?.filter(
Expand Down
111 changes: 60 additions & 51 deletions app/src/components/side-bar/SideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { useAppSelector } from "@hooks/useGlobalState";
import BlockList from "@features/privacy-settings/BlockList";
import Devices from "@features/devices/Devices";
import NewGroup from "@features/groups/NewGroup.js";
import { SidebarContext } from "./SideBarContext.js";

interface SideBarProps {
rows?: SideBarRowProps[];
Expand Down Expand Up @@ -65,57 +66,63 @@ const StyledSidebar = styled.aside<{ $isExiting: boolean }>`
}
`;

const sideBarMap: { [key: string]: (props: SideBarProps) => React.ReactNode } =
{
Chats: () => (
<ChatsSideBar>
<ChatList />
</ChatsSideBar>
),
Contacts: () => <ContactsSideBar />,
Settings: (props) => (
<SettingsSideBar rows={props.rows || []}>
<ProfilePicture />
<ProfileInfo />
</SettingsSideBar>
),
Privacy: (props) => <SettingsSideBar rows={props.rows || []} />,
SettingsUpdate: (props) => (
<SettingsSideBar rows={[]}>
{props.data && <SettingsUpdate {...props.data} />}
</SettingsSideBar>
),
ProfileUpdate: () => <ProfileSettings />,
blockList: () => (
<SettingsSideBar rows={[]}>
<BlockList />
</SettingsSideBar>
),
Devices: () => <SettingsSideBar rows={[]} children={<Devices />} />,
AddMembers: (props) => (
<SettingsSideBar rows={[]}>
<AddGroupMembers type={props.data?.type!} />
</SettingsSideBar>
),
NewGroup: () => (
<SettingsSideBar rows={[]}>
<NewGroup type="group" />
</SettingsSideBar>
),
NewChannel: () => (
<SettingsSideBar rows={[]}>
<NewGroup type="channel" />
</SettingsSideBar>
),
};

function Sidebar() {
const { page, props } = useAppSelector((state) => state.sideBarData);
const sideBarMap: {
[key: string]: (
props: SideBarProps,
type: "left" | "right"
) => React.ReactNode;
} = {
Chats: () => (
<ChatsSideBar>
<ChatList />
</ChatsSideBar>
),
Contacts: () => <ContactsSideBar />,
Settings: (props) => (
<SettingsSideBar rows={props.rows || []}>
<ProfilePicture />
<ProfileInfo />
</SettingsSideBar>
),
Privacy: (props) => <SettingsSideBar rows={props.rows || []} />,
SettingsUpdate: (props) => (
<SettingsSideBar rows={[]}>
{props.data && <SettingsUpdate {...props.data} />}
</SettingsSideBar>
),
ProfileUpdate: () => <ProfileSettings />,
blockList: () => (
<SettingsSideBar rows={[]}>
<BlockList />
</SettingsSideBar>
),
Devices: () => <SettingsSideBar rows={[]} children={<Devices />} />,
AddMembers: (props) => (
<SettingsSideBar rows={[]}>
<AddGroupMembers type={props.data?.type!} />
</SettingsSideBar>
),
NewGroup: () => (
<SettingsSideBar rows={[]}>
<NewGroup type="group" />
</SettingsSideBar>
),
NewChannel: () => (
<SettingsSideBar rows={[]}>
<NewGroup type="channel" />
</SettingsSideBar>
),
};

function Sidebar({ type }: { type: "left" | "right" }) {
const { page, props } = useAppSelector((state) =>
type === "left"
? state.sideBarData.leftSideBar
: state.sideBarData.rightSideBar
);
const [currentPage, setCurrentPage] = useState(page);
const [isExiting, setIsExiting] = useState(false);

console.log(currentPage);

useEffect(() => {
if (currentPage !== page) {
setIsExiting(true);
Expand All @@ -133,9 +140,11 @@ function Sidebar() {
const pageString = pagesMap[currentPage] || "Settings";

return (
<StyledSidebar $isExiting={isExiting} data-testid="side-bar">
{sideBarMap[pageString](props || {})}
</StyledSidebar>
<SidebarContext.Provider value={type}>
<StyledSidebar $isExiting={isExiting} data-testid={`${type}-side-bar`}>
{sideBarMap[pageString](props!, type)}
</StyledSidebar>
</SidebarContext.Provider>
);
}

Expand Down
13 changes: 13 additions & 0 deletions app/src/components/side-bar/SideBarContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { createContext, useContext } from "react";

type SidebarType = "left" | "right";

export const SidebarContext = createContext<SidebarType | undefined>(undefined);

export const useSidebarType = () => {
const context = useContext(SidebarContext);
if (!context) {
throw new Error("useSidebarType must be used within a SidebarProvider");
}
return context;
};
12 changes: 8 additions & 4 deletions app/src/components/side-bar/chats/SideBarToolsButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { updateSideBarView } from "@state/side-bar/sideBar";
import { sideBarPages } from "@data/sideBar";
import { useMouseLeave } from "@hooks/useMouseLeave";
import { getIcon } from "@data/icons";
import { useSidebarType } from "../SideBarContext";
import { RootState } from "@state/store";
import { clearSearch } from "@state/messages/global-search";
import { useSelector } from "react-redux";
Expand Down Expand Up @@ -58,6 +59,9 @@ function SettingsToolbar() {
dispatch(clearSearch());
};


const type = useSidebarType();

return (
<>
<ToolsIcon
Expand All @@ -83,8 +87,8 @@ function SettingsToolbar() {
dispatch(
updateSideBarView({
redirect: sideBarPages.CONTACTS,
data: undefined,
}),
data: { type },
})
)
}
/>
Expand All @@ -96,8 +100,8 @@ function SettingsToolbar() {
dispatch(
updateSideBarView({
redirect: sideBarPages.SETTINGS,
data: undefined,
}),
data: { type },
})
)
}
/>
Expand Down
10 changes: 8 additions & 2 deletions app/src/components/side-bar/settings/OptionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
StatusType,
} from "types/sideBar";
import { statusMap } from "@data/sideBar";
import { useSidebarType } from "../SideBarContext";

const StyledOptionsList = styled.div`
display: flex;
Expand All @@ -32,7 +33,7 @@ function getKey(
| permissionSettingsID
| undefined,
type: StatusType | undefined,
index: number,
index: number
) {
let key;
if (status !== undefined && type !== undefined) {
Expand All @@ -48,8 +49,13 @@ function getKey(
}

function OptionsList({ rows }: { rows: SideBarRowProps[] }) {
const { title } = useAppSelector((state) => state.sideBarData);
const type = useSidebarType();

const { title } = useAppSelector((state) =>
type === "left"
? state.sideBarData.leftSideBar
: state.sideBarData.rightSideBar
);
return (
<>
{rows.length > 0 && (
Expand Down
14 changes: 12 additions & 2 deletions app/src/components/side-bar/settings/SettingsSideBarHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import CircleIcon from "@components/CircleIcon";
import { useLogout } from "@features/authentication/logout/hooks/useLogout";
import { updateSideBarView } from "@state/side-bar/sideBar";
import { sideBarPages } from "types/sideBar";
import { useSidebarType } from "../SideBarContext";

const StyledSideBarHeader = styled.div`
height: 4rem !important;
Expand All @@ -32,7 +33,13 @@ const IconsContainer = styled.div`
`;

function SettingsSideBarHeader() {
const { title } = useAppSelector((state) => state.sideBarData);
const type = useSidebarType();

const { title } = useAppSelector((state) =>
type === "left"
? state.sideBarData.leftSideBar
: state.sideBarData.rightSideBar
);
const { logout } = useLogout();
const dispatch = useAppDispatch();

Expand All @@ -53,7 +60,10 @@ function SettingsSideBarHeader() {
$bgColor="var(--color-pattern)"
onClick={() =>
dispatch(
updateSideBarView({ redirect: sideBarPages.PROFILE_UPDATE })
updateSideBarView({
redirect: sideBarPages.PROFILE_UPDATE,
data: { type },
})
)
}
/>
Expand Down
Loading

0 comments on commit b8abb66

Please sign in to comment.