Refactor components (#81)

This commit is contained in:
Maria Rushkova 2021-10-18 16:35:32 +02:00 committed by GitHub
parent a34dbeeb32
commit c929c26172
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 319 additions and 292 deletions

View File

@ -1,55 +1,10 @@
import React, { useEffect, useMemo } from "react"; import React, { useMemo } from "react";
import styled from "styled-components"; import styled from "styled-components";
import { useNarrow } from "../contexts/narrowProvider"; import { useNarrow } from "../../contexts/narrowProvider";
import { ChannelData, channels } from "../helpers/channelsMock"; import { ChannelData } from "../../helpers/channelsMock";
import { MutedIcon } from "../Icons/MutedIcon";
import { MutedIcon } from "./Icons/MutedIcon"; import { textMediumStyles } from "../Text";
import { textMediumStyles } from "./Text";
interface ChannelsProps {
notifications: { [id: string]: number };
clearNotifications: (id: string) => void;
onCommunityClick: (val: ChannelData) => void;
activeChannelId: number;
}
export function Channels({
notifications,
onCommunityClick,
clearNotifications,
activeChannelId,
}: ChannelsProps) {
useEffect(() => {
const channel = channels.find((channel) => channel.id === activeChannelId);
if (channel) {
if (notifications[channel.name] > 0) {
clearNotifications(channel.name);
}
}
}, [notifications, activeChannelId]);
return (
<ChannelList>
{channels.map((channel) => (
<Channel
key={channel.id}
channel={channel}
isActive={channel.id === activeChannelId}
isMuted={channel.isMuted || false}
notification={
notifications[channel.name] > 0 && !channel.isMuted
? notifications[channel.name]
: undefined
}
onClick={() => {
onCommunityClick(channel);
}}
/>
))}
</ChannelList>
);
}
interface ChannelProps { interface ChannelProps {
channel: ChannelData; channel: ChannelData;
@ -118,26 +73,6 @@ export function Channel({
); );
} }
const ChannelDescription = styled.p`
font-size: 12px;
line-height: 16px;
letter-spacing: 0.1px;
color: ${({ theme }) => theme.secondary};
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
`;
export const ChannelList = styled.div`
display: flex;
flex-direction: column;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 0;
}
`;
const ChannelWrapper = styled.div` const ChannelWrapper = styled.div`
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -216,6 +151,16 @@ export const ChannelName = styled.p`
} }
`; `;
const ChannelDescription = styled.p`
font-size: 12px;
line-height: 16px;
letter-spacing: 0.1px;
color: ${({ theme }) => theme.secondary};
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
`;
const NotificationBagde = styled.div` const NotificationBagde = styled.div`
width: 24px; width: 24px;
height: 24px; height: 24px;

View File

@ -0,0 +1,60 @@
import React, { useEffect } from "react";
import styled from "styled-components";
import { ChannelData, channels } from "../../helpers/channelsMock";
import { Channel } from "./Channel";
interface ChannelsProps {
notifications: { [id: string]: number };
clearNotifications: (id: string) => void;
onCommunityClick: (val: ChannelData) => void;
activeChannelId: number;
}
export function Channels({
notifications,
onCommunityClick,
clearNotifications,
activeChannelId,
}: ChannelsProps) {
useEffect(() => {
const channel = channels.find((channel) => channel.id === activeChannelId);
if (channel) {
if (notifications[channel.name] > 0) {
clearNotifications(channel.name);
}
}
}, [notifications, activeChannelId]);
return (
<ChannelList>
{channels.map((channel) => (
<Channel
key={channel.id}
channel={channel}
isActive={channel.id === activeChannelId}
isMuted={channel.isMuted || false}
notification={
notifications[channel.name] > 0 && !channel.isMuted
? notifications[channel.name]
: undefined
}
onClick={() => {
onCommunityClick(channel);
}}
/>
))}
</ChannelList>
);
}
export const ChannelList = styled.div`
display: flex;
flex-direction: column;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 0;
}
`;

View File

@ -1,10 +1,10 @@
import React from "react"; 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 { textMediumStyles } from "../Text";
import { ChannelInfo, ChannelLogo, ChannelName } from "./Channels"; import { ChannelInfo, ChannelLogo, ChannelName } from "./Channel";
import { textMediumStyles } from "./Text";
type EmptyChannelProps = { type EmptyChannelProps = {
channel: ChannelData; channel: ChannelData;

View File

@ -8,10 +8,10 @@ import { useMessenger } from "../hooks/useMessenger";
import { Metadata } from "../models/Metadata"; import { Metadata } from "../models/Metadata";
import { Theme } from "../styles/themes"; import { Theme } from "../styles/themes";
import { Channels } from "./Channels"; import { Channels } from "./Channels/Channels";
import { ChatBody } from "./Chat/ChatBody"; import { ChatBody } from "./Chat/ChatBody";
import { Community } from "./Community"; import { Community } from "./Community";
import { Members } from "./Members"; import { Members } from "./Members/Members";
import { CommunityModal } from "./Modals/CommunityModal"; import { CommunityModal } from "./Modals/CommunityModal";
interface ChatProps { interface ChatProps {

View File

@ -7,9 +7,9 @@ import { CommunityData } from "../../helpers/communityMock";
import { ChatMessage } from "../../models/ChatMessage"; import { ChatMessage } from "../../models/ChatMessage";
import { Metadata } from "../../models/Metadata"; import { Metadata } from "../../models/Metadata";
import { Theme } from "../../styles/themes"; import { Theme } from "../../styles/themes";
import { Channel } from "../Channels"; import { Channel } from "../Channels/Channel";
import { EmptyChannel } from "../Channels/EmptyChannel";
import { Community } from "../Community"; import { Community } from "../Community";
import { EmptyChannel } from "../EmptyChannel";
import { MembersIcon } from "../Icons/MembersIcon"; import { MembersIcon } from "../Icons/MembersIcon";
import { NarrowChannels } from "../NarrowMode/NarrowChannels"; import { NarrowChannels } from "../NarrowMode/NarrowChannels";
import { NarrowMembers } from "../NarrowMode/NarrowMembers"; import { NarrowMembers } from "../NarrowMode/NarrowMembers";

View File

@ -1,212 +0,0 @@
import React, { useCallback } from "react";
import styled from "styled-components";
import { useNarrow } from "../contexts/narrowProvider";
import { CommunityData } from "../helpers/communityMock";
import { Icon } from "./Chat/ChatMessages";
import { UserIcon } from "./Icons/UserIcon";
interface MembersProps {
community: CommunityData;
setShowChannels: (val: boolean) => void;
}
export function Members({ community, setShowChannels }: MembersProps) {
return (
<MembersWrapper>
<MemberHeading>Members</MemberHeading>
<MembersList community={community} setShowChannels={setShowChannels} />
</MembersWrapper>
);
}
interface MembersListProps {
community: CommunityData;
setShowChannels: (val: boolean) => void;
setShowMembers?: (val: boolean) => void;
}
export function MembersList({
community,
setShowChannels,
setShowMembers,
}: MembersListProps) {
return (
<MembersListWrap>
<MemberCategory>
<MemberCategoryName>You</MemberCategoryName>
<MemberData>
<MemberIcon>
<UserIcon memberView={true} />
</MemberIcon>
<MemberName>Guest564732</MemberName>
</MemberData>
</MemberCategory>
<MemberCategory>
<MemberCategoryName>Online</MemberCategoryName>
{community.membersList
.filter((member) => member.isOnline)
.map((member) => (
<Member
key={member.id}
member={member}
isOnline={member.isOnline}
setShowChannels={setShowChannels}
setShowMembers={setShowMembers}
/>
))}
</MemberCategory>
<MemberCategory>
<MemberCategoryName>Offline</MemberCategoryName>
{community.membersList
.filter((member) => !member.isOnline)
.map((member) => (
<Member
key={member.id}
member={member}
isOnline={member.isOnline}
setShowChannels={setShowChannels}
setShowMembers={setShowMembers}
/>
))}
</MemberCategory>
</MembersListWrap>
);
}
interface MemberProps {
member: any;
isOnline: boolean;
setShowChannels: (val: boolean) => void;
setShowMembers?: (val: boolean) => void;
}
export function Member({
member,
isOnline,
setShowChannels,
setShowMembers,
}: MemberProps) {
const narrow = useNarrow();
const switchMemberList = useCallback(() => {
setShowChannels(false);
if (setShowMembers) setShowMembers(false);
}, [setShowMembers]);
return (
<MemberData
onClick={() =>
narrow && setShowMembers ? switchMemberList() : setShowChannels(true)
}
>
<MemberIcon
style={{
backgroundImage: member.avatar ? `url(${member.avatar})` : "unset",
}}
className={isOnline ? "online" : "offline"}
>
{!member.avatar && <UserIcon memberView={true} />}
</MemberIcon>
<MemberName>{member.name}</MemberName>
</MemberData>
);
}
const MembersWrapper = styled.div`
width: 18%;
height: 100%;
min-width: 164px;
display: flex;
flex-direction: column;
background-color: ${({ theme }) => theme.sectionBackgroundColor};
padding: 16px;
`;
const MemberHeading = styled.h2`
font-weight: 500;
font-size: 15px;
line-height: 22px;
color: ${({ theme }) => theme.primary};
margin-bottom: 16px;
`;
const MemberCategoryName = styled.h3`
font-weight: normal;
font-size: 13px;
line-height: 18px;
color: ${({ theme }) => theme.secondary};
margin-bottom: 8px;
`;
const MemberName = styled.p`
font-weight: 500;
font-size: 15px;
line-height: 22px;
color: ${({ theme }) => theme.primary};
opacity: 0.7;
margin-left: 8px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
`;
const MembersListWrap = styled.div`
display: flex;
flex-direction: column;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 0;
}
`;
const MemberCategory = styled.div`
display: flex;
flex-direction: column;
margin-bottom: 16px;
`;
const MemberData = styled.div`
display: flex;
align-items: center;
margin-bottom: 16px;
`;
const MemberIcon = styled(Icon)`
width: 24px;
height: 24px;
position: relative;
background-size: contain;
background-position: center;
flex-shrink: 0;
&.offline {
&::after {
content: "";
position: absolute;
right: -1px;
bottom: -2px;
width: 7px;
height: 7px;
border-radius: 50%;
background-color: ${({ theme }) => theme.secondary};
border: 2px solid ${({ theme }) => theme.bodyBackgroundColor};
}
}
&.online {
&::after {
content: "";
position: absolute;
right: -1px;
bottom: -2px;
width: 7px;
height: 7px;
border-radius: 50%;
background-color: #4ebc60;
border: 2px solid ${({ theme }) => theme.bodyBackgroundColor};
}
}
`;

View File

@ -0,0 +1,100 @@
import React, { useCallback } from "react";
import styled from "styled-components";
import { useNarrow } from "../../contexts/narrowProvider";
import { Icon } from "../Chat/ChatMessages";
import { UserIcon } from "../Icons/UserIcon";
interface MemberProps {
member: any;
isOnline: boolean;
setShowChannels: (val: boolean) => void;
setShowMembers?: (val: boolean) => void;
}
export function Member({
member,
isOnline,
setShowChannels,
setShowMembers,
}: MemberProps) {
const narrow = useNarrow();
const switchMemberList = useCallback(() => {
setShowChannels(false);
if (setShowMembers) setShowMembers(false);
}, [setShowMembers]);
return (
<MemberData
onClick={() =>
narrow && setShowMembers ? switchMemberList() : setShowChannels(true)
}
>
<MemberIcon
style={{
backgroundImage: member.avatar ? `url(${member.avatar})` : "unset",
}}
className={isOnline ? "online" : "offline"}
>
{!member.avatar && <UserIcon memberView={true} />}
</MemberIcon>
<MemberName>{member.name}</MemberName>
</MemberData>
);
}
export const MemberData = styled.div`
display: flex;
align-items: center;
margin-bottom: 16px;
`;
export const MemberName = styled.p`
font-weight: 500;
font-size: 15px;
line-height: 22px;
color: ${({ theme }) => theme.primary};
opacity: 0.7;
margin-left: 8px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
`;
export const MemberIcon = styled(Icon)`
width: 24px;
height: 24px;
position: relative;
background-size: contain;
background-position: center;
flex-shrink: 0;
&.offline {
&::after {
content: "";
position: absolute;
right: -1px;
bottom: -2px;
width: 7px;
height: 7px;
border-radius: 50%;
background-color: ${({ theme }) => theme.secondary};
border: 2px solid ${({ theme }) => theme.bodyBackgroundColor};
}
}
&.online {
&::after {
content: "";
position: absolute;
right: -1px;
bottom: -2px;
width: 7px;
height: 7px;
border-radius: 50%;
background-color: #4ebc60;
border: 2px solid ${({ theme }) => theme.bodyBackgroundColor};
}
}
`;

View File

@ -0,0 +1,38 @@
import React from "react";
import styled from "styled-components";
import { CommunityData } from "../../helpers/communityMock";
import { MembersList } from "./MembersList";
interface MembersProps {
community: CommunityData;
setShowChannels: (val: boolean) => void;
}
export function Members({ community, setShowChannels }: MembersProps) {
return (
<MembersWrapper>
<MemberHeading>Members</MemberHeading>
<MembersList community={community} setShowChannels={setShowChannels} />
</MembersWrapper>
);
}
const MembersWrapper = styled.div`
width: 18%;
height: 100%;
min-width: 164px;
display: flex;
flex-direction: column;
background-color: ${({ theme }) => theme.sectionBackgroundColor};
padding: 16px;
`;
const MemberHeading = styled.h2`
font-weight: 500;
font-size: 15px;
line-height: 22px;
color: ${({ theme }) => theme.primary};
margin-bottom: 16px;
`;

View File

@ -0,0 +1,97 @@
import React from "react";
import styled from "styled-components";
import { CommunityData } from "../../helpers/communityMock";
import { UserIcon } from "../Icons/UserIcon";
import { Member, MemberData, MemberIcon } from "./Member";
interface MembersListProps {
community: CommunityData;
setShowChannels: (val: boolean) => void;
setShowMembers?: (val: boolean) => void;
}
export function MembersList({
community,
setShowChannels,
setShowMembers,
}: MembersListProps) {
return (
<MembersListWrap>
<MemberCategory>
<MemberCategoryName>You</MemberCategoryName>
<MemberData>
<MemberIcon>
<UserIcon memberView={true} />
</MemberIcon>
<MemberName>Guest564732</MemberName>
</MemberData>
</MemberCategory>
<MemberCategory>
<MemberCategoryName>Online</MemberCategoryName>
{community.membersList
.filter((member) => member.isOnline)
.map((member) => (
<Member
key={member.id}
member={member}
isOnline={member.isOnline}
setShowChannels={setShowChannels}
setShowMembers={setShowMembers}
/>
))}
</MemberCategory>
<MemberCategory>
<MemberCategoryName>Offline</MemberCategoryName>
{community.membersList
.filter((member) => !member.isOnline)
.map((member) => (
<Member
key={member.id}
member={member}
isOnline={member.isOnline}
setShowChannels={setShowChannels}
setShowMembers={setShowMembers}
/>
))}
</MemberCategory>
</MembersListWrap>
);
}
const MembersListWrap = styled.div`
display: flex;
flex-direction: column;
overflow-y: scroll;
&::-webkit-scrollbar {
width: 0;
}
`;
const MemberCategory = styled.div`
display: flex;
flex-direction: column;
margin-bottom: 16px;
`;
const MemberCategoryName = styled.h3`
font-weight: normal;
font-size: 13px;
line-height: 18px;
color: ${({ theme }) => theme.secondary};
margin-bottom: 8px;
`;
const MemberName = styled.p`
font-weight: 500;
font-size: 15px;
line-height: 22px;
color: ${({ theme }) => theme.primary};
opacity: 0.7;
margin-left: 8px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
`;

View File

@ -2,7 +2,7 @@ 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 { Channels } from "../Channels"; import { Channels } from "../Channels/Channels";
import { NarrowTopbar } from "./NarrowTopbar"; import { NarrowTopbar } from "./NarrowTopbar";

View File

@ -2,7 +2,7 @@ import React from "react";
import styled from "styled-components"; import styled from "styled-components";
import { CommunityData } from "../../helpers/communityMock"; import { CommunityData } from "../../helpers/communityMock";
import { MembersList } from "../Members"; import { MembersList } from "../Members/MembersList";
import { NarrowTopbar } from "./NarrowTopbar"; import { NarrowTopbar } from "./NarrowTopbar";

View File

@ -1 +0,0 @@
export const Font = "Inter, sans-serif";