import React, {
useState,
useEffect,
useMemo,
useCallback,
useRef,
} from 'react';
import styled from '@emotion/styled';
import Image from '@components/common/Image';
import MoreOptionsContainer from '@components/main/Sidebar/MoreOptionsContainer';
import Modal from '@components/common/Modal';
import { useUserInfo } from '@contexts/UserInfoProvider';
import colors from '@assets/colors';
import useLocalStorage from '@hooks/useLocalStorage';
import { css } from '@emotion/react';
const SidebarContainer = styled.aside`
position: fixed;
background: #252b2e;
width: 500px;
height: 100%;
color: #fff;
`;
const HeaderContainer = styled.div`
display: flex;
`;
const SidebarHeader = styled.header`
display: flex;
align-items: center;
justify-content: center;
background: #5fb3b3;
width: calc(100% - 50px);
height: 50px;
`;
const ToggleButton = styled.button`
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
width: 50px;
height: 50px;
`;
const UserListContainer = styled.div`
margin: 40px 16px;
background: rgba(256, 256, 256, 0.1);
padding: 0 16px;
height: 500px;
`;
const UserInfoCount = styled.div`
padding: 20px 0;
height: 30px;
`;
const UserList = styled.div`
margin: 0;
padding: 0;
height: 400px;
overflow-y: auto;
list-style: none;
`;
const UserCard = styled.div`
box-sizing: border-box;
display: flex;
background: rgba(256, 256, 256, 0.1);
padding: 16px;
color: #fff;
&:not(:last-child) {
margin-bottom: 8px;
}
`;
const UserAuthBadge = styled.div`
${({ visible }) =>
visible
? css`
display: block;
`
: css`
display: none;
`}
position: absolute;
left: -10px;
top: -10px;
width: 16px;
height: 16px;
border-radius: 50%;
background: ${colors.default.green};
`;
const UserInfo = styled.div`
margin-left: 16px;
`;
const Username = styled.div`
font-size: 20px;
`;
const UserDoing = styled.div`
font-size: 16px;
`;
const UserImageContainer = styled.div`
position: relative;
border-radius: 50px;
width: 50px;
height: 50px;
`;
const MyInfoContainer = styled.div`
position: absolute;
bottom: 0;
width: 100%;
`;
const ShowMoreButton = styled.button`
transform: ${({ isActive }) => (isActive ? `rotate(90deg)` : '')};
transition: transform 0.3s;
margin-left: auto;
width: 60px;
height: 50px;
`;
const ModalUserTime = styled.h2``;
const ModalLogoutHeader = styled.h1``;
const ModalButtonBox = styled.ul`
display: flex;
`;
const ModalConfirmButton = styled.button`
background-color: ${colors.default.green};
`;
const ModalCancelButton = styled(ModalConfirmButton)`
background-color: ${colors.default.red};
`;
const ModalTagDropdown = styled.section`
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
`;
const DropdownHeader = styled.h3`
strong {
font-weight: 700;
}
`;
const DropdownForm = styled.form`
display: block;
width: 100%;
height: 30px;
`;
const DropdownInput = styled.input`
width: 100%;
height: 100%;
box-sizing: border-box;
`;
const TagList = styled.ul`
overflow-y: scroll;
height: 240px;
`;
const TagItem = styled.li`
display: flex;
align-items: center;
padding: 0px 4px;
width: 100%;
height: 36px;
font-size: 20px;
box-sizing: border-box;
&:hover {
background-color: ${colors.secondary300};
}
`;
const TagItemTodo = styled.div`
font-weight: bold;
`;
const TagItemRemoveButton = styled.button`
display: none;
margin-left: auto;
&.active {
display: block;
}
`;
const ConfirmButton = styled(ModalConfirmButton)``;
const Sidebar = ({ users, isAuth, usersAuth }) => {
const { userInfo, emptyUserInfo } = useUserInfo();
const sidebarRef = useRef(null);
const placeholder = useMemo(
() =>
'https://mblogthumb-phinf.pstatic.net/MjAxODEyMDVfMjY5/MDAxNTQ0MDA3NDgyNjgw.v21vfp4yFzGtYlNrFPeo7Cxkd6ZVa3ZNKeRwZe5l3e0g.y2pAI3tJYWq04q_FwbVgTOoTVo9bKcwISdhj9EAxNYgg.GIF.nang723/IMG_0834.GIF?type=w800',
[]
);
const [isShowMoreButtonActive, setIsShowMoreButtonActive] = useState(false);
const [mousePosition, setMousePosition] = useState({
x: 0,
y: 0,
width: 0,
height: 0,
});
const handleShowMoreButtonClick = useCallback(({ clientX, clientY }) => {
setIsShowMoreButtonActive((state) => !state);
setMousePosition(() => ({
x: clientX,
y: clientY,
width: document.body.clientWidth,
height: sidebarRef.current.clientHeight,
}));
}, []);
const [isStepOut, setIsStepOut] = useState(false);
const handleStepOutButtonClick = () => {
setIsStepOut((state) => !state);
setIsShowMoreButtonActive(false);
};
const [visible, setVisible] = useState(false);
const handleLogoutButtonClick = () => {
setVisible(() => true);
};
useEffect(() => {
if (!visible) {
setIsShowMoreButtonActive(() => false);
}
}, [visible]);
const [visibleDropdown, setVisibleDropdown] = useState(false);
const handleTagButtonClick = () => {
setVisibleDropdown(() => true);
};
const inputRef = useRef(null);
const [tags, setTags] = useLocalStorage('tags', []);
const [nowTag, setNowTag] = useState('');
const [inputTagValue, setInputTagValue] = useState('');
const [filteredTags, setFilteredTags] = useState([]);
useEffect(() => {
if (inputTagValue) {
setFilteredTags(() => tags);
}
setFilteredTags(() => tags.filter((tag) => tag.includes(inputTagValue)));
console.log(filteredTags);
}, [inputTagValue]);
const handleInput = (e) => {
console.log(e.target.value);
setInputTagValue(inputRef.current.value);
};
const handleNowTagChange = (e) => {
e.preventDefault();
if (!inputTagValue) {
return;
}
setTags([...new Set([...tags, inputValue])]);
setInputTagValue(() => '');
};
const handleTagItemClick = (e) => {
const closestLi = e.target.closest('li');
if (!closestLi) return;
if (e.target.classList.contains('tagRemoveButton')) {
setTags((state) =>
state.filter(
(content) => content !== closestLi.querySelector('div').textContent
)
);
return;
}
const value = closestLi.querySelector('div').textContent;
setInputTagValue(() => '');
setNowTag(value);
setVisibleDropdown(() => false);
setIsShowMoreButtonActive(() => false);
};
const isBadgeVisible = (id) => {
return usersAuth.includes(id);
};
const handleTagItemHover = (e) => {
const closestLi = e.target.closest('li');
if (!closestLi) return;
const activeButton = closestLi.querySelector('button');
e.currentTarget.querySelectorAll('li > button').forEach((buttonElement) => {
buttonElement.classList.toggle('active', buttonElement === activeButton);
});
};
return (
<SidebarContainer ref={sidebarRef}>
<HeaderContainer>
<SidebarHeader>방 이름</SidebarHeader>
<ToggleButton>토글!</ToggleButton>
</HeaderContainer>
<UserListContainer>
<UserInfoCount>함께하는 사람들: {users.length}명</UserInfoCount>
<UserList>
{users.map(({ image, _id, fullName, updatedAt }) => (
<UserCard key={_id}>
<UserImageContainer>
<UserAuthBadge visible={isBadgeVisible(_id)} />
<Image
src={image}
lazy
block
width={50}
height={50}
placeholder={placeholder}
alt="profile"
isCircle
/>
</UserImageContainer>
<UserInfo>
<Username>{fullName}</Username>
<UserDoing>{updatedAt}</UserDoing>
</UserInfo>
</UserCard>
))}
</UserList>
</UserListContainer>
<MyInfoContainer>
<UserCard>
<UserImageContainer>
<UserAuthBadge visible={isAuth} />
<Image
src={userInfo.image}
lazy
block
width={50}
height={50}
placeholder={placeholder}
alt="profile"
isCircle
/>
</UserImageContainer>
<UserInfo>
<Username>{userInfo.fullName}</Username>
<UserDoing>{isStepOut ? `🚫 자리비움` : nowTag}</UserDoing>
</UserInfo>
<ShowMoreButton
isActive={isShowMoreButtonActive}
onClick={handleShowMoreButtonClick}
>
미트볼 버튼
</ShowMoreButton>
<MoreOptionsContainer
visible={isShowMoreButtonActive}
mousePosition={mousePosition}
onClose={() => !visible && setIsShowMoreButtonActive(false)}
>
<button type="button" onClick={handleStepOutButtonClick}>
{isStepOut ? `자리비움 취소` : `자리비움`}
</button>
<button type="button" onClick={handleLogoutButtonClick}>
로그아웃
</button>
<button type="button" onClick={handleTagButtonClick}>
할 일 수정
</button>
</MoreOptionsContainer>
<Modal
isDimBlack
width={400}
height={400}
visible={visible || visibleDropdown}
onClose={() => {
if (visible) setVisible(() => false);
if (visibleDropdown) setVisibleDropdown(() => false);
}}
>
{visible && (
<>
<ModalUserTime>{`현재 ${userInfo.fullName}님이 모각코한 시간: `}</ModalUserTime>
<ModalLogoutHeader>
정말로 로그아웃 하시겠어요?
</ModalLogoutHeader>
<ModalButtonBox>
<ModalConfirmButton onClick={emptyUserInfo}>
확인
</ModalConfirmButton>
<ModalCancelButton
className="modal__cancel-button"
onClick={() => {
setVisible(() => false);
}}
>
취소
</ModalCancelButton>
</ModalButtonBox>
</>
)}
{visibleDropdown && (
<ModalTagDropdown>
<DropdownHeader>
현재 하고 있는 일을 <strong>반.드.시</strong> 입력하세요!
</DropdownHeader>
<DropdownForm onSubmit={handleNowTagChange}>
<DropdownInput ref={inputRef} onInput={handleInput} />
<TagList
onClick={handleTagItemClick}
onMouseOver={handleTagItemHover}
>
{/* {!inputTagValue
? tags.map((tag) => (
<TagItem key={tag}>
<TagItemTodo>{tag}</TagItemTodo>
<TagItemRemoveButton
type="button"
className="tagRemoveButton"
>
❌
</TagItemRemoveButton>
</TagItem>
))
: tags
.filter((content) => content.includes(inputTagValue))
.map((tag) => (
<TagItem key={tag}>
<TagItemTodo>{tag}</TagItemTodo>
<TagItemRemoveButton
type="button"
className="tagRemoveButton"
>
❌
</TagItemRemoveButton>
</TagItem>
))} */}
</TagList>
</DropdownForm>
<ConfirmButton onClick={handleNowTagChange}>
할 일 추가
</ConfirmButton>
</ModalTagDropdown>
)}
</Modal>
</UserCard>
</MyInfoContainer>
</SidebarContainer>
);
};
export default Sidebar;