Skip to content

Commit

Permalink
feat: 우선순위 결과에서 해당 시간대에 불가능한 사람 수 표시 (#133)
Browse files Browse the repository at this point in the history
* fix: update font weight

* feat: add accordion component
  • Loading branch information
corinthionia authored Dec 7, 2024
1 parent b1b3ee1 commit 2e328ed
Show file tree
Hide file tree
Showing 14 changed files with 277 additions and 89 deletions.
3 changes: 3 additions & 0 deletions src/assets/icons/accordionUnfold.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 changes: 82 additions & 0 deletions src/components/commons/accordion/index.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import theme from '@/styles/theme';
import styled from '@emotion/styled';

export const Wrapper = styled.div`
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
`;

export const Group = styled.section`
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
`;

export const GroupInfo = styled.div`
display: flex;
${theme.colors.gray07};
${theme.typography.medium01};
`;

export const ListWrapper = styled.div`
width: 100%;
height: 0px;
overflow: hidden;
transition: height 0.35s ease, background 0.35s ease;
`;

export const AccordionIcon = styled.img<{ isCollapsed: boolean }>`
transition: transform 0.3s ease;
transform: ${({ isCollapsed }) =>
isCollapsed ? 'rotate(0deg)' : 'rotate(180deg)'};
`;

export const ItemWrapper = styled.div`
padding: 16px 0 0 0;
display: flex;
flex-direction: column;
gap: 10px;
`;

export const Item = styled.div`
width: 100%;
display: flex;
flex-direction: column;
gap: 4px;
`;

export const InfoText = styled.div`
color: #979797;
${theme.typography.medium05};
.available {
color: ${theme.colors.purple06};
}
.unavailable {
color: ${theme.colors.orange02};
}
`;

export const NameList = styled.div`
width: 100%;
display: flex;
flex-wrap: wrap;
gap: 4px;
`;

export const NameBlock = styled.div`
width: 46.5px;
height: 24px;
background: #ffffff;
display: flex;
align-items: center;
justify-content: center;
border-radius: 2.8px;
${theme.typography.medium05};
color: ${theme.colors.gray05};
`;
106 changes: 106 additions & 0 deletions src/components/commons/accordion/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { useEffect, useRef, useState } from 'react';
import {
AccordionIcon,
Group,
GroupInfo,
InfoText,
Item,
ItemWrapper,
ListWrapper,
NameBlock,
NameList,
Wrapper,
} from './index.styles';
import accordionUnfold from '@/assets/icons/accordionUnfold.svg';

interface Props {
title: string;
defaultOpen?: boolean;
totalCount: number;
availableParticipantNames: string[];
unavailableParticipantNames: string[];
}

const Accordion = ({
title,
defaultOpen = false,
totalCount,
availableParticipantNames,
unavailableParticipantNames,
}: Props) => {
const parentRef = useRef<HTMLDivElement>(null);
const childRef = useRef<HTMLDivElement>(null);

const [isCollapsed, setIsCollapsed] = useState<boolean>(defaultOpen);

useEffect(() => {
if (defaultOpen && parentRef.current && childRef.current) {
parentRef.current.style.height = `${childRef.current.clientHeight}px`;
}
}, [defaultOpen]);

const handleClickAccordion = () => {
if (
totalCount === 0 ||
parentRef.current === null ||
childRef.current === null
) {
return;
}

if (parentRef.current.clientHeight > 0) {
parentRef.current.style.height = '0px';
} else if (parentRef.current.clientHeight === 0) {
parentRef.current.style.height = `${childRef.current.clientHeight}px`;
}

setIsCollapsed(!isCollapsed);
};

return (
<Wrapper>
<Group onClick={handleClickAccordion}>
<GroupInfo>{title}</GroupInfo>
{!!totalCount && (
<AccordionIcon
src={accordionUnfold}
alt={isCollapsed ? '펼치기' : '접기'}
isCollapsed={isCollapsed}
/>
)}
</Group>

<ListWrapper ref={parentRef}>
<ItemWrapper ref={childRef}>
<Item>
<InfoText>
<span>{`${totalCount}명 중 `}</span>
<span className="available">{`${availableParticipantNames.length}명 가능`}</span>
</InfoText>
<NameList>
{!!availableParticipantNames.length &&
availableParticipantNames.map((name) => (
<NameBlock key={name}>{name.slice(0, 4)}</NameBlock>
))}
</NameList>
</Item>

<Item>
<InfoText>
<span>{`${totalCount}명 중 `}</span>
<span className="unavailable">{`${unavailableParticipantNames.length}명 불가능`}</span>
</InfoText>
<NameList>
{!!unavailableParticipantNames.length &&
unavailableParticipantNames.map((name) => (
<NameBlock key={name}>{name.slice(0, 4)}</NameBlock>
))}
</NameList>
</Item>
</ItemWrapper>
</ListWrapper>
</Wrapper>
);
};

export default Accordion;
26 changes: 0 additions & 26 deletions src/components/result/candidate/index.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,29 +45,3 @@ export const TimeWrapper = styled.div`
color: ${theme.colors.gray06};
${theme.typography.semibold03};
`;

export const ListItem = styled.div`
width: 100%;
margin-top: 14px;
display: flex;
flex-flow: wrap;
row-gap: 4px;
column-gap: 4px;
`;

export const Participant = styled.div`
min-width: 44px;
border-radius: 3px;
padding: 4px 5px;
${theme.typography.medium05};
color: ${theme.colors.gray05};
background: ${theme.colors.gray01};
display: flex;
align-items: center;
justify-content: center;
`;
40 changes: 14 additions & 26 deletions src/components/result/candidate/index.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import {
Content,
ListItem,
Participant,
People,
ProportionWrapper,
TimeWrapper,
Wrapper,
} from './index.styles';
import Accordion from '@/components/commons/accordion';
import { Wrapper } from './index.styles';
import { CandidateTypes } from './index.types';

const Candidate = ({
date,
dayOfWeek,
startTime,
endTime,
participantNames,
count,
availableParticipantNames,
unavailableParticipantNames,
defaultOpen = false,
}: CandidateTypes) => {
const convertDateFormat = () => {
if (startTime && endTime) {
Expand All @@ -30,21 +24,15 @@ const Candidate = ({

return (
<Wrapper>
<Content>
{count !== null && (
<ProportionWrapper>
<People isParticipant={false}>{count}명 중</People>
<People isParticipant={true}> {participantNames.length}</People>
</ProportionWrapper>
)}
<TimeWrapper>{convertDateFormat()}</TimeWrapper>
</Content>

<ListItem>
{participantNames.map((name: string) => (
<Participant key={name}>{name}</Participant>
))}
</ListItem>
<Accordion
title={convertDateFormat()}
availableParticipantNames={availableParticipantNames}
unavailableParticipantNames={unavailableParticipantNames}
totalCount={
availableParticipantNames.length + unavailableParticipantNames.length
}
defaultOpen={defaultOpen}
/>
</Wrapper>
);
};
Expand Down
4 changes: 3 additions & 1 deletion src/components/result/candidate/index.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ export interface CandidateTypes {
dayOfWeek: string;
startTime: string;
endTime: string;
participantNames: string[];
availableParticipantNames: string[];
unavailableParticipantNames: string[];
count: number | null;
defaultOpen?: boolean;
}
2 changes: 1 addition & 1 deletion src/hooks/useShareLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useParams } from 'react-router-dom';

const useShareLink = () => {
const { roomUUID } = useParams();
const inviteURL = `${window.location.origin}${ROUTES.INVITE}/${roomUUID}`;
const inviteURL = `${window.location.origin}${ROUTES.INVITE}/${roomUUID}?utm_source=user&utm_campaign=user_invite`;

const handleUseShareAPI = () => {
const shareData = {
Expand Down
6 changes: 4 additions & 2 deletions src/pages/landing/index.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export const IntroWrapper = styled.div`
color: ${theme.colors.gray01};
${theme.typography.semibold04};
font-size: 22px;
font-weight: 500;
transition: 1s;
transform: translateY(10px);
}
Expand All @@ -118,7 +119,8 @@ export const IntroWrapper = styled.div`
opacity: 0;
.section-text {
font-size: 28px;
font-size: 20px;
font-weight: 500;
}
}
`;
Expand Down Expand Up @@ -185,7 +187,7 @@ export const LastWrapper = styled.div`
.title {
color: ${theme.colors.gray01};
${theme.typography.semibold02}
${theme.typography.medium01};
}
`;

Expand Down
2 changes: 1 addition & 1 deletion src/pages/landing/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const Landing = () => {
<img className="chat" src={landing1} />
<div className="section">
<div className="section-logo">
<img className="logo" src={Logo} />
<img className="logo" src={Logo} />
</div>
<div className="section-text">도와드릴게요!</div>
</div>
Expand Down
14 changes: 5 additions & 9 deletions src/pages/result/index.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export const SelectWrapper = styled.div`

export const NobodyWrapper = styled.div`
width: 100%;
height: 161px;
padding: 28px 0;
margin-top: 14px;
border-radius: 7px;
Expand All @@ -57,22 +57,18 @@ export const NobodyWrapper = styled.div`
`;

export const Nobody = styled.div`
width: 188px;
height: 105px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
gap: 8px;
`;

export const NobodyRabbit = styled.img`
width: 50px;
height: 68px;
width: 37px;
height: 49px;
object-fit: scale-down;
`;

export const NobodyText = styled.span`
color: ${theme.colors.gray04};
${theme.typography.semibold03};
${theme.typography.medium02};
`;
Loading

0 comments on commit 2e328ed

Please sign in to comment.