Extract channel component (#27)

This commit is contained in:
Maria Rushkova 2021-10-01 14:50:20 +02:00 committed by GitHub
parent f0dec3d5af
commit e4710c3445
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 153 additions and 66 deletions

View File

@ -2,26 +2,25 @@ import React, { useEffect } from "react";
import styled from "styled-components"; import styled from "styled-components";
import { ChannelData, channels } from "../helpers/channelsMock"; import { ChannelData, channels } from "../helpers/channelsMock";
import { CommunityData } from "../helpers/communityMock";
import { Theme } from "../styles/themes"; import { Theme } from "../styles/themes";
import { Community, MembersAmount } from "./Community";
import { MutedIcon } from "./Icons/MutedIcon"; import { MutedIcon } from "./Icons/MutedIcon";
interface ChannelsProps { interface ChannelsProps {
theme: Theme; theme: Theme;
icon: string; community: CommunityData;
name: string;
notifications: { [id: string]: number }; notifications: { [id: string]: number };
clearNotifications: (id: string) => void; clearNotifications: (id: string) => void;
members: number;
setActiveChannel: (val: ChannelData) => void; setActiveChannel: (val: ChannelData) => void;
activeChannelId: number; activeChannelId: number;
} }
export function Channels({ export function Channels({
theme, theme,
icon, community,
name,
members,
notifications, notifications,
setActiveChannel, setActiveChannel,
clearNotifications, clearNotifications,
@ -38,13 +37,7 @@ export function Channels({
return ( return (
<ChannelsWrapper theme={theme}> <ChannelsWrapper theme={theme}>
<Community> <Community community={community} theme={theme} />
<CommunityLogo src={icon} alt={`${name} logo`} />
<CommunityInfo>
<CommunityName theme={theme}>{name}</CommunityName>
<MembersAmount theme={theme}>{members} members</MembersAmount>
</CommunityInfo>
</Community>
<ChannelList> <ChannelList>
{channels.map((channel) => ( {channels.map((channel) => (
<Channel <Channel
@ -146,41 +139,10 @@ const ChannelsWrapper = styled.div<ThemeProps>`
flex-direction: column; flex-direction: column;
`; `;
const Community = styled.div`
display: flex;
margin-bottom: 16px;
`;
const CommunityLogo = styled.img`
width: 36px;
height: 36px;
border-radius: 50%;
margin-left: 10px;
`;
const CommunityInfo = styled.div`
display: flex;
flex-direction: column;
margin-left: 8px;
`;
const CommunityName = styled.h1<ThemeProps>`
font-weight: 500;
font-size: 15px;
line-height: 22px;
color: ${({ theme }) => theme.textPrimaryColor};
`;
const MembersAmount = styled.p<ThemeProps>`
font-size: 12px;
line-height: 16px;
letter-spacing: 0.1px;
color: ${({ theme }) => theme.textSecondaryColor};
`;
const ChannelList = styled.div` const ChannelList = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin-top: 16px;
`; `;
const ChannelWrapper = styled.div<ThemeProps>` const ChannelWrapper = styled.div<ThemeProps>`

View File

@ -2,6 +2,7 @@ import React, { useState } from "react";
import styled from "styled-components"; import styled from "styled-components";
import { ChannelData, channels } from "../helpers/channelsMock"; import { ChannelData, channels } from "../helpers/channelsMock";
import { CommunityData } from "../helpers/communityMock";
import { useMessenger } from "../hooks/useMessenger"; import { useMessenger } from "../hooks/useMessenger";
import { Theme } from "../styles/themes"; import { Theme } from "../styles/themes";
@ -11,12 +12,13 @@ import { Members } from "./Members";
interface ChatProps { interface ChatProps {
theme: Theme; theme: Theme;
channelsON?: boolean; community: CommunityData;
} }
export function Chat({ theme, channelsON }: ChatProps) { export function Chat({ theme, community }: ChatProps) {
const [activeChannel, setActiveChannel] = useState<ChannelData>(channels[0]); const [activeChannel, setActiveChannel] = useState<ChannelData>(channels[0]);
const [showMembers, setShowMembers] = useState(true); const [showMembers, setShowMembers] = useState(true);
const [showChannels, setShowChannels] = useState(false);
const { const {
messenger, messenger,
@ -31,14 +33,12 @@ export function Chat({ theme, channelsON }: ChatProps) {
return ( return (
<ChatWrapper> <ChatWrapper>
{channelsON && ( {showChannels && (
<Channels <Channels
notifications={notifications} notifications={notifications}
clearNotifications={clearNotifications} clearNotifications={clearNotifications}
theme={theme} theme={theme}
icon={"https://www.cryptokitties.co/icons/logo.svg"} community={community}
name={"CryptoKitties"}
members={186}
setActiveChannel={setActiveChannel} setActiveChannel={setActiveChannel}
activeChannelId={activeChannel.id} activeChannelId={activeChannel.id}
/> />
@ -51,11 +51,19 @@ export function Chat({ theme, channelsON }: ChatProps) {
sendMessage={sendMessage} sendMessage={sendMessage}
onClick={() => setShowMembers(!showMembers)} onClick={() => setShowMembers(!showMembers)}
showMembers={showMembers} showMembers={showMembers}
community={community}
showCommunity={!showChannels}
/> />
) : ( ) : (
<Loading>Connecting to waku</Loading> <Loading>Connecting to waku</Loading>
)} )}
{showMembers && <Members theme={theme} channel={activeChannel} />} {showMembers && (
<Members
theme={theme}
channel={activeChannel}
setShowChannels={setShowChannels}
/>
)}
</ChatWrapper> </ChatWrapper>
); );
} }

View File

@ -2,9 +2,11 @@ import React from "react";
import styled from "styled-components"; import styled from "styled-components";
import { ChannelData } from "../../helpers/channelsMock"; import { ChannelData } from "../../helpers/channelsMock";
import { CommunityData } from "../../helpers/communityMock";
import { ChatMessage } from "../../models/ChatMessage"; import { ChatMessage } from "../../models/ChatMessage";
import { Theme } from "../../styles/themes"; import { Theme } from "../../styles/themes";
import { Channel } from "../Channels"; import { Channel } from "../Channels";
import { Community } from "../Community";
import { MembersIcon } from "../Icons/MembersIcon"; import { MembersIcon } from "../Icons/MembersIcon";
import { ChatInput } from "./ChatInput"; import { ChatInput } from "./ChatInput";
@ -13,23 +15,33 @@ import { ChatMessages } from "./ChatMessages";
interface ChatBodyProps { interface ChatBodyProps {
theme: Theme; theme: Theme;
channel: ChannelData; channel: ChannelData;
community: CommunityData;
messages: ChatMessage[]; messages: ChatMessage[];
sendMessage: (text: string) => void; sendMessage: (text: string) => void;
onClick: () => void; onClick: () => void;
showMembers: boolean; showMembers: boolean;
showCommunity: boolean;
} }
export function ChatBody({ export function ChatBody({
theme, theme,
channel, channel,
community,
messages, messages,
sendMessage, sendMessage,
onClick, onClick,
showMembers, showMembers,
showCommunity,
}: ChatBodyProps) { }: ChatBodyProps) {
return ( return (
<ChatBodyWrapper theme={theme}> <ChatBodyWrapper theme={theme}>
<ChatTopbar>
<ChannelWrapper> <ChannelWrapper>
{showCommunity && (
<CommunityWrap theme={theme}>
<Community community={community} theme={theme} />
</CommunityWrap>
)}
<Channel <Channel
channel={channel} channel={channel}
theme={theme} theme={theme}
@ -37,6 +49,7 @@ export function ChatBody({
activeView={true} activeView={true}
isMuted={false} isMuted={false}
/> />
</ChannelWrapper>
<MemberBtn <MemberBtn
onClick={onClick} onClick={onClick}
className={showMembers ? "active" : ""} className={showMembers ? "active" : ""}
@ -44,7 +57,7 @@ export function ChatBody({
> >
<MembersIcon theme={theme} /> <MembersIcon theme={theme} />
</MemberBtn> </MemberBtn>
</ChannelWrapper> </ChatTopbar>
<ChatMessages messages={messages} theme={theme} /> <ChatMessages messages={messages} theme={theme} />
<ChatInput theme={theme} addMessage={sendMessage} /> <ChatInput theme={theme} addMessage={sendMessage} />
</ChatBodyWrapper> </ChatBodyWrapper>
@ -59,15 +72,39 @@ const ChatBodyWrapper = styled.div<ThemeProps>`
flex-direction: column; flex-direction: column;
flex: 1; flex: 1;
height: 100%; height: 100%;
background: ${({ theme }) => theme.bodyBackgroundColor}; background: ${({ theme }) => theme.textPrimaryColor};
`; `;
const ChannelWrapper = styled.div` const ChannelWrapper = styled.div`
display: flex;
align-items: center;
`;
const ChatTopbar = styled.div`
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
padding: 0 8px; padding: 0 8px;
`; `;
const CommunityWrap = styled.div<ThemeProps>`
padding-right: 16px;
margin-right: 16px;
position: relative;
&:after {
content: "";
position: absolute;
right: 0;
top: 50%;
width: 2px;
height: 24px;
transform: translateY(-50%);
border-radius: 1px;
background: ${({ theme }) => theme.bodyBackgroundColor};
opacity: 0.1;
}
`;
const MemberBtn = styled.button<ThemeProps>` const MemberBtn = styled.button<ThemeProps>`
width: 32px; width: 32px;
height: 32px; height: 32px;

View File

@ -0,0 +1,57 @@
import React from "react";
import styled from "styled-components";
import { CommunityData } from "../helpers/communityMock";
import { Theme } from "../styles/themes";
interface CommunityProps {
theme: Theme;
community: CommunityData;
}
export function Community({ theme, community }: CommunityProps) {
return (
<CommunityWrap>
<CommunityLogo src={community.icon} alt={`${community.name} logo`} />
<CommunityInfo>
<CommunityName theme={theme}>{community.name}</CommunityName>
<MembersAmount theme={theme}>{community.members} members</MembersAmount>
</CommunityInfo>
</CommunityWrap>
);
}
interface ThemeProps {
theme: Theme;
}
const CommunityWrap = styled.div`
display: flex;
`;
const CommunityLogo = styled.img`
width: 36px;
height: 36px;
border-radius: 50%;
margin-left: 10px;
`;
const CommunityInfo = styled.div`
display: flex;
flex-direction: column;
margin-left: 8px;
`;
const CommunityName = styled.h1<ThemeProps>`
font-weight: 500;
font-size: 15px;
line-height: 22px;
color: ${({ theme }) => theme.textPrimaryColor};
`;
export const MembersAmount = styled.p<ThemeProps>`
font-size: 12px;
line-height: 16px;
letter-spacing: 0.1px;
color: ${({ theme }) => theme.textSecondaryColor};
`;

View File

@ -10,9 +10,10 @@ import { UserIcon } from "./Icons/UserIcon";
interface MembersProps { interface MembersProps {
theme: Theme; theme: Theme;
channel: ChannelData; channel: ChannelData;
setShowChannels: (val: boolean) => void;
} }
export function Members({ theme, channel }: MembersProps) { export function Members({ theme, channel, setShowChannels }: MembersProps) {
return ( return (
<MembersWrapper theme={theme}> <MembersWrapper theme={theme}>
<MemberHeading theme={theme}>Members</MemberHeading> <MemberHeading theme={theme}>Members</MemberHeading>
@ -36,6 +37,7 @@ export function Members({ theme, channel }: MembersProps) {
theme={theme} theme={theme}
member={member} member={member}
isOnline={member.isOnline} isOnline={member.isOnline}
setShowChannels={setShowChannels}
/> />
))} ))}
</MemberCategory> </MemberCategory>
@ -49,6 +51,7 @@ export function Members({ theme, channel }: MembersProps) {
theme={theme} theme={theme}
member={member} member={member}
isOnline={member.isOnline} isOnline={member.isOnline}
setShowChannels={setShowChannels}
/> />
))} ))}
</MemberCategory> </MemberCategory>
@ -61,11 +64,17 @@ interface MemberProps {
theme: Theme; theme: Theme;
member: any; member: any;
isOnline: boolean; isOnline: boolean;
setShowChannels: (val: boolean) => void;
} }
export function Member({ theme, member, isOnline }: MemberProps) { export function Member({
theme,
member,
isOnline,
setShowChannels,
}: MemberProps) {
return ( return (
<MemberData> <MemberData onClick={() => setShowChannels(true)}>
<MemberIcon <MemberIcon
style={{ style={{
backgroundImage: member.avatar ? `url(${member.avatar})` : "unset", backgroundImage: member.avatar ? `url(${member.avatar})` : "unset",

View File

@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import { community } from "../helpers/communityMock";
import { GlobalStyle } from "../styles/GlobalStyle"; import { GlobalStyle } from "../styles/GlobalStyle";
import { lightTheme } from "../styles/themes"; import { lightTheme } from "../styles/themes";
@ -9,7 +10,7 @@ export function ReactChat() {
return ( return (
<div> <div>
<GlobalStyle /> <GlobalStyle />
<Chat channelsON={true} theme={lightTheme} /> <Chat theme={lightTheme} community={community} />
</div> </div>
); );
} }

View File

@ -0,0 +1,13 @@
export type CommunityData = {
id: number;
name: string;
icon: string;
members: number;
};
export const community = {
id: 1,
name: "CryptoKitties",
icon: "https://www.cryptokitties.co/icons/logo.svg",
members: 186,
};