diff --git a/src/assets/svgs/dropdown.svg b/src/assets/svgs/dropdown.svg new file mode 100644 index 00000000..9db502db --- /dev/null +++ b/src/assets/svgs/dropdown.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgs/dropup.svg b/src/assets/svgs/dropup.svg new file mode 100644 index 00000000..cc22f537 --- /dev/null +++ b/src/assets/svgs/dropup.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/svgs/member.svg b/src/assets/svgs/member.svg new file mode 100644 index 00000000..93c67214 --- /dev/null +++ b/src/assets/svgs/member.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/assets/svgs/tooltipArrow.svg b/src/assets/svgs/tooltipArrow.svg index 016dbd1a..2a0ea213 100644 --- a/src/assets/svgs/tooltipArrow.svg +++ b/src/assets/svgs/tooltipArrow.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/src/components/Icon/icon.ts b/src/components/Icon/icon.ts index 09694526..4462adad 100644 --- a/src/components/Icon/icon.ts +++ b/src/components/Icon/icon.ts @@ -4,8 +4,10 @@ import { ReactComponent as Circle2Ic } from 'assets/svgs/circle2.svg'; import { ReactComponent as Circle3Ic } from 'assets/svgs/circle3.svg'; import { ReactComponent as ClockIc } from 'assets/svgs/clock.svg'; import { ReactComponent as CloseIc } from 'assets/svgs/close.svg'; +import { ReactComponent as DropDown } from 'assets/svgs/dropdown.svg'; import { ReactComponent as DropDownIc } from 'assets/svgs/dropDownBtn.svg'; import { ReactComponent as DropdownWhite } from 'assets/svgs/dropdownWhite.svg'; +import { ReactComponent as DropUp } from 'assets/svgs/dropup.svg'; import { ReactComponent as DropUpIc } from 'assets/svgs/dropUpBtn.svg'; import { ReactComponent as DropupWhite } from 'assets/svgs/dropupWhite.svg'; import { ReactComponent as ExitIc } from 'assets/svgs/exitIcon.svg'; @@ -15,6 +17,7 @@ import { ReactComponent as InputErrorIc } from 'assets/svgs/inputErrorBtn.svg'; import { ReactComponent as LinkIc } from 'assets/svgs/linkIcon.svg'; import { ReactComponent as LinkTooltipIc } from 'assets/svgs/linkTooltip.svg'; import { ReactComponent as MainLogoIc } from 'assets/svgs/mainLogo.svg'; +import { ReactComponent as Member } from 'assets/svgs/member.svg'; import { ReactComponent as OfflinePlaceIc } from 'assets/svgs/offlinePlace.svg'; import { ReactComponent as OnlinePlaceIc } from 'assets/svgs/onlinePlace.svg'; import { ReactComponent as PasswordEyeIc } from 'assets/svgs/passwordEye.svg'; @@ -58,4 +61,12 @@ export { TimeIc, TooltipArrowIc, Wave, + Circle1Ic, + Circle2Ic, + Circle3Ic, + CloseIc, + DropUp, + DropDown, + Member, + TooltipArrowIc, }; diff --git a/src/pages/bestMeetTime/ChooseBestTime.tsx b/src/pages/bestMeetTime/ChooseBestTime.tsx index 34655f16..541b0356 100644 --- a/src/pages/bestMeetTime/ChooseBestTime.tsx +++ b/src/pages/bestMeetTime/ChooseBestTime.tsx @@ -43,26 +43,37 @@ const ChangeViewPicker = styled.div<{ $isClicked: boolean }>` margin-top: 2.5rem; ${({ theme }) => theme.fonts.body2}; border-bottom: 2px solid; + border-color: ${({ $isClicked, theme, id }) => + id === 'best' + ? $isClicked + ? theme.colors.main1 + : theme.colors.grey5 + : $isClicked + ? theme.colors.grey5 + : theme.colors.main1}; width: 18.7rem; height: 3.5rem; color: ${({ $isClicked, theme, id }) => id === 'best' ? $isClicked - ? theme.colors.main1 - : theme.colors.grey4 + ? theme.colors.white + : theme.colors.grey5 : $isClicked - ? theme.colors.grey4 - : theme.colors.main1}; + ? theme.colors.grey5 + : theme.colors.white}; ${({ $isClicked, theme, id }) => id === 'best' ? $isClicked - ? theme.colors.main1 + ? theme.colors.white : theme.colors.grey4 : $isClicked ? theme.colors.grey4 - : theme.colors.main1}; + : theme.colors.white}; `; const ViewContainer = styled.div` display: flex; align-items: center; + width: 100%; + margin-top: 3.6rem; + margin-bottom: 16.4rem; `; diff --git a/src/pages/bestMeetTime/components/AlternativeCard.tsx b/src/pages/bestMeetTime/components/AlternativeCard.tsx deleted file mode 100644 index b45ec624..00000000 --- a/src/pages/bestMeetTime/components/AlternativeCard.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import Text from 'components/common/atomComponents/Text'; -import { BestDataProps } from 'pages/bestMeetTime/types/meetCardData'; -import styled from 'styled-components'; -import { theme } from 'styles/theme'; - -function AlternativeCard({ rank, carddata, chooseMeetime, selected }: BestDataProps) { - const checkingCheck = () => { - chooseMeetime(rank); - }; - - if (carddata) { - return ( - - - - - - - {carddata.users.map((member, i) => ( - - {member.name} - {i !== carddata.users.length - 1 ? ',' : ''}  - - ))} - - - - ); - } else { - return null; - } -} - -export default AlternativeCard; - -const AlternativeCardWrapper = styled.article<{ $rank: number; $selected: number }>` - display: flex; - position: relative; - flex-direction: row; - border: 1px solid - ${({ $rank, $selected, theme }) => - $rank === $selected ? theme.colors.main1 : theme.colors.grey5}; - border-radius: 10px; - padding: 2rem; - height: fit-content; -`; - -const InfoContainer = styled.div` - display: flex; - flex-direction: column; - color: ${({ theme }) => theme.colors.white}; -`; -const Input = styled.input` - appearance: none; - margin: 0 2.274rem 0 0; - background-image: url("data:image/svg+xml,%3Csvg width='20' height='20' viewBox='0 0 20 20' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='10' cy='10' r='9' stroke='%23D9D9D9' stroke-width='2'/%3E%3C/svg%3E%0A"); - background-repeat: no-repeat; - cursor: pointer; - width: 2rem; - height: 2rem; - - &:checked { - background-image: url("data:image/svg+xml,%3Csvg width='20' height='20' viewBox='0 0 20 20' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='10' cy='10' r='10' fill='%233C49FF'/%3E%3Ccircle cx='9.99965' cy='10.0001' r='3.63636' fill='white'/%3E%3C/svg%3E "); - } - &:checked + label { - color: ${({ theme }) => theme.colors.white}; - } -`; -const Label = styled.label` - display: flex; - flex-direction: column; - align-items: flex-start; - cursor: pointer; -`; - -const MemeberContainer = styled.div` - display: flex; - flex-direction: row; - flex-wrap: wrap; - margin-top: 1.2rem; - width: 23rem; - height: fit-content; -`; diff --git a/src/pages/bestMeetTime/components/BestMeetTime.tsx b/src/pages/bestMeetTime/components/BestMeetTime.tsx index 311a8809..f76c1a7b 100644 --- a/src/pages/bestMeetTime/components/BestMeetTime.tsx +++ b/src/pages/bestMeetTime/components/BestMeetTime.tsx @@ -2,8 +2,7 @@ import React, { useState } from 'react'; import Button from 'components/common/atomComponents/Button'; import Text from 'components/common/atomComponents/Text'; -import { DropdownWhite, DropupWhite } from 'components/Icon/icon'; -import AlternativeCard from 'pages/bestMeetTime/components/AlternativeCard'; +import { DropDown, DropUp } from 'components/Icon/icon'; import BestTimeCard from 'pages/bestMeetTime/components/BestTimeCard'; import ConfirmModal from 'pages/bestMeetTime/components/ConfirmModal'; import GetBestMeetimeListHooks from 'pages/bestMeetTime/hooks/getBestMeetimeList'; @@ -15,6 +14,7 @@ import styled from 'styled-components'; import { theme } from 'styles/theme'; import BlankMeetCard from './BlankMeetCard'; +import BlankOtherMeetCard from './BlankOtherMeetCard'; function BestMeetTime() { const [isalternativeCardOpen, setIsalternativeCardOpen] = useState(false); @@ -27,35 +27,43 @@ function BestMeetTime() { const navigate = useNavigate(); if (isError) { navigate(`/*`); - } else if (!isloading && bestTimeData) { - const bestMeetimeObj = whatisBestMeetime(bestTimeData, selected); - if (bestMeetimeObj) { - return ( - - - - - - 현재까지 모인  - - - {bestTimeData.data.memberCount} - - - 명 - - - 을 위한 - - - - 최적의 회의시간이에요 - - - - 박스를 클릭하여 회의시간을 확정해주세요 + } + if (isloading) { + return ( + + + + ); + } + const bestMeetimeObj = bestTimeData && whatisBestMeetime(bestTimeData, selected); + return ( + + + + + + 현재까지 모인  + + + {bestTimeData ? bestTimeData.data.memberCount : ''} - + + 명 + + + 을 위한 + + + + 최적의 회의시간이에요 + + + + 박스를 클릭하여 회의시간을 확정해주세요 + + + {bestMeetimeObj ? ( + <> {bestTimeData.data.bestDateTime ? ( ) : null} - - setIsalternativeCardOpen((prev) => !prev)}> - - 다른 시간대 확인하기 - - - {isalternativeCardOpen ? : } - - - {isalternativeCardOpen ? ( - - {bestTimeData.data.otherDateTimes[0] ? ( - - ) : ( - - )} - {bestTimeData.data.otherDateTimes[1] ? ( - - ) : null} - + + ) : ( + + )} + setIsalternativeCardOpen((prev) => !prev)}> + + 다른 시간대 확인하기 + + {isalternativeCardOpen ? : } + + {isalternativeCardOpen && bestTimeData ? ( + + {bestTimeData.data.otherDateTimes[0] ? ( + ) : ( - undefined + )} - - - - {showModal && ( - - )} - - ); - } - } else { - return ( - - - - ); - } + ) : null} + + ) : null} + + + + {showModal && + bestMeetimeObj && ( + + )} + + ); } export default BestMeetTime; @@ -134,8 +134,9 @@ const BestMeetTimeWrapper = styled.div<{ $state: boolean }>` const TitleSection = styled.article` display: flex; flex-direction: column; - margin: 4rem 10.8rem 3rem 0rem; + width: 100%; + margin-bottom: 3.6rem; `; const HeaderContainer = styled.div` margin-bottom: 1.2rem; @@ -151,11 +152,12 @@ const AnotherTimeBtnSection = styled.div` justify-content: flex-end; margin: 2rem 0 1.6rem 0; padding-right: 1rem; + cursor: pointer; `; const AlternativeSection = styled.section` display: flex; flex-direction: column; - gap: 1rem; + gap: 1.6rem; `; const BasicIconContainer = styled.div` display: flex; diff --git a/src/pages/bestMeetTime/components/BestTimeCard.tsx b/src/pages/bestMeetTime/components/BestTimeCard.tsx index e20f3b88..bdba9e78 100644 --- a/src/pages/bestMeetTime/components/BestTimeCard.tsx +++ b/src/pages/bestMeetTime/components/BestTimeCard.tsx @@ -1,22 +1,18 @@ -import React, { useState } from 'react'; - import Text from 'components/common/atomComponents/Text'; -import { DropdownWhite, DropupWhite } from 'components/Icon/icon'; +import { Member } from 'components/Icon/icon'; import { BestDataProps } from 'pages/bestMeetTime/types/meetCardData'; import styled from 'styled-components'; import { theme } from 'styles/theme'; +import MemberTooltip from './MemberTooltip'; + function BestTimeCard({ rank, carddata, chooseMeetime, selected }: BestDataProps) { - const [isMember, setIsMember] = useState(false); const checkingCheck = () => { chooseMeetime(rank); }; if (carddata) { return ( - setIsMember((prev) => !prev)}> - {isMember ? : } - - {isMember ? ( - - {carddata.users.map((member, i) => ( - - {member.name} - {i !== carddata.users.length - 1 ? ',' : ''}  - - ))} - - ) : ( - undefined - )} + + + + {carddata.users.length} + + + user.name)} /> ); - } else { - return undefined; } } @@ -60,9 +49,9 @@ const BestTimeCardWrapper = styled.article<{ $rank: number; $selected: number }> flex-direction: row; border: 1px solid ${({ $rank, $selected, theme }) => - $rank === $selected ? theme.colors.main1 : theme.colors.grey5}; + $rank === $selected ? theme.colors.main1 : theme.colors.grey7}; border-radius: 10px; - padding: 2rem; + padding: 1.8rem 1.5rem; width: 100%; height: fit-content; `; @@ -74,7 +63,7 @@ const InfoContainer = styled.div` const Input = styled.input` appearance: none; margin: 0 2.274rem 0 0; - background-image: url("data:image/svg+xml,%3Csvg width='20' height='20' viewBox='0 0 20 20' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='10' cy='10' r='9' stroke='%23D9D9D9' stroke-width='2'/%3E%3C/svg%3E%0A"); + background-image: url("data:image/svg+xml,%3Csvg width='20' height='20' viewBox='0 0 20 20' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='10' cy='10' r='9' stroke='%23555555' stroke-width='2'/%3E%3C/svg%3E%0A"); background-repeat: no-repeat; cursor: pointer; width: 2rem; @@ -94,25 +83,27 @@ const Label = styled.label` cursor: pointer; `; -const MemeberContainer = styled.div` - display: flex; - flex-direction: row; - flex-wrap: wrap; - margin-top: 1.2rem; - width: 23rem; - height: fit-content; -`; - -const BasicIconContainer = styled.div` +const MemberCountChip = styled.div` display: flex; - align-items: center; justify-content: center; - width: 3rem; + align-items: center; + min-width: 5.6rem; height: 3rem; -`; + padding: 0.6rem 1rem; + gap: 0.6rem; + border-radius: 10rem; + background-color: ${theme.colors.grey8}; + align-self: flex-end; + margin-left: auto; + cursor: pointer; + &:hover { + background-color: ${theme.colors.grey5}; + } + &:focus { + background-color: ${theme.colors.grey6}; + } -const IconContainer = styled(BasicIconContainer)` - position: absolute; - top: 1.2rem; - right: 1.2rem; + &:hover + .tooltip { + visibility: visible; + } `; diff --git a/src/pages/bestMeetTime/components/BlankMeetCard.tsx b/src/pages/bestMeetTime/components/BlankMeetCard.tsx index 158a6423..7ae5bf1a 100644 --- a/src/pages/bestMeetTime/components/BlankMeetCard.tsx +++ b/src/pages/bestMeetTime/components/BlankMeetCard.tsx @@ -1,5 +1,3 @@ -import React from 'react'; - import Text from 'components/common/atomComponents/Text'; import styled from 'styled-components'; import { theme } from 'styles/theme'; @@ -7,8 +5,8 @@ import { theme } from 'styles/theme'; function BlankMeetCard() { return ( - - 입력된 다른 시간대가 없어요! + + 산출된 회의 시간이 없어요! ); @@ -20,8 +18,7 @@ const BlankMeetCardWrapper = styled.div` display: flex; align-items: center; justify-content: center; - border: 1px solid ${({ theme }) => theme.colors.grey5}; + border: 1px solid ${({ theme }) => theme.colors.grey7}; border-radius: 1rem; - width: 33.5rem; - height: 5.2rem; + padding: 3.4rem 0; `; diff --git a/src/pages/bestMeetTime/components/BlankOtherMeetCard.tsx b/src/pages/bestMeetTime/components/BlankOtherMeetCard.tsx new file mode 100644 index 00000000..efe46c45 --- /dev/null +++ b/src/pages/bestMeetTime/components/BlankOtherMeetCard.tsx @@ -0,0 +1,24 @@ +import Text from 'components/common/atomComponents/Text'; +import styled from 'styled-components'; +import { theme } from 'styles/theme'; + +function BlankOtherMeetCard() { + return ( + + + 산출된 회의 시간이 없어요! + + + ); +} + +export default BlankOtherMeetCard; + +const BlankOtherMeetCardWrapper = styled.div` + display: flex; + align-items: center; + justify-content: center; + border: 1px solid ${({ theme }) => theme.colors.grey7}; + border-radius: 1rem; + padding: 1.8rem 0; +`; diff --git a/src/pages/bestMeetTime/components/MemberTooltip.tsx b/src/pages/bestMeetTime/components/MemberTooltip.tsx new file mode 100644 index 00000000..f1fa0728 --- /dev/null +++ b/src/pages/bestMeetTime/components/MemberTooltip.tsx @@ -0,0 +1,55 @@ +import Text from 'components/common/atomComponents/Text'; +import { TooltipArrowIc } from 'components/Icon/icon'; +import styled from 'styled-components'; +import { theme } from 'styles/theme'; + +interface MemberTooltipProps { + members: string[]; +} + +function MemberTooltip({ members }: MemberTooltipProps) { + return ( + + + + + {members.join(', ')} + + + + ); +} + +export default MemberTooltip; +const MemberTooltipWrapper = styled.div` + visibility: hidden; + z-index: 1; + position: absolute; + width: fit-content; + right: 4%; + top: 90%; +`; + +const TooltipArrowIcon = styled(TooltipArrowIc)` + position: absolute; + top: -0.6rem; + right: 1.3rem; + + path { + fill: ${({ theme }) => theme.colors.grey3}; + } +`; +const TooltipContent = styled.div` + display: flex; + justify-content: center; + align-items: center; + padding: 0.4rem 0.8rem; + border-radius: 0.6rem; + background-color: ${theme.colors.grey3}; + width: fit-content; + text-align: center; + span { + white-space: pre; + word-break: unset; + } +`; diff --git a/src/pages/overallSchedule/components/OverallScheduleColumn.tsx b/src/pages/overallSchedule/components/OverallScheduleColumn.tsx index 27ac0275..709c276a 100644 --- a/src/pages/overallSchedule/components/OverallScheduleColumn.tsx +++ b/src/pages/overallSchedule/components/OverallScheduleColumn.tsx @@ -25,10 +25,10 @@ function OverallScheduleColumn({ date, timeSlots, availableSlotInfo }: OverallSc /** * 종합일정 시간표 스타일링 - * 1. border-top: 선택된 시간이라면 none, 선택되지 않은 시간이라면 30분 단위는 none, 1시간 단위는 실선 + * 1. border-top: 선택된 시간이라면 none, 선택되지 않은 시간이라면 30분 단위는 점선, 1시간 단위는 실선 * 2. background-color: 선택된 시간이라면 colorLevel에 따른 색상 */ - const borderTopStyle = slotId.endsWith(':30') ? 'none' : 'solid'; + const borderTopStyle = slotId.endsWith(':30') ? 'dashed' : 'solid'; const borderTop = `1px ${borderTopStyle} ${theme.colors.grey7} `; const isClickedSlot = clickedSlot === slotId; const backgroundColor = isClickedSlot && colorLevel !== 0 ? theme.colors.sub1 : COLOR[colorLevel]; diff --git a/src/pages/overallSchedule/components/Title.tsx b/src/pages/overallSchedule/components/Title.tsx index 44835bd1..1338f022 100644 --- a/src/pages/overallSchedule/components/Title.tsx +++ b/src/pages/overallSchedule/components/Title.tsx @@ -24,7 +24,7 @@ function Title({ memberCount, totalUserNames }: TitleProps) { {totalUserNames && ( - {totalUserNames.join(',')} + {totalUserNames.join(', ')} )} @@ -37,7 +37,6 @@ export default Title; const TextOneLine = styled.div` display: flex; flex-wrap: wrap; - margin-top: 3.7rem; width: 100%; `; diff --git a/src/pages/overallSchedule/components/UserNames.tsx b/src/pages/overallSchedule/components/UserNames.tsx index f02dff29..fa0558ff 100644 --- a/src/pages/overallSchedule/components/UserNames.tsx +++ b/src/pages/overallSchedule/components/UserNames.tsx @@ -8,22 +8,24 @@ function UserNames() { const { clickedUserNames } = useClickContext(); return ( - - {clickedUserNames.length === 0 ? ( - - - 블럭을 선택하면 해당 시간대에 참여가능한 + + + {clickedUserNames.length === 0 ? ( + + + 블럭을 선택하면 해당 시간대에 참여가능한 + + + 인원을 확인할 수 있어요 + + + ) : ( + + {clickedUserNames.join(', ')} - - 인원을 확인할 수 있어요 - - - ) : ( - - {clickedUserNames.join(', ')} - - )} - + )} + + ); } @@ -31,7 +33,7 @@ export default UserNames; const UserNamesWrapper = styled.aside` display: flex; - position: fixed; + bottom: 4.4rem; flex-wrap: wrap; justify-content: center; @@ -50,3 +52,22 @@ const Texts = styled.div` align-items: center; justify-content: center; `; + +const Dim = styled.div` + display: flex; + position: fixed; + bottom: 0; + gap: 1rem; + align-items: end; + justify-content: center; + z-index: 2; + height: 16.4rem; + + margin-top: 3rem; + background: ${({ theme }) => theme.colors.dim_gradient}; + padding-bottom: 2.9rem; + + width: 100%; + + pointer-events: none; +`;