-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gmmq 690 style: 메인 페이지 UI 리터칭 #242
Merged
Merged
Changes from 5 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
b19ba73
feat: 직무 썸네일 이미지 추가
khakhiD ff15bd7
fix: '진행중인 이벤트'를 '진행 중인 피드백'으로 수정
khakhiD d21fdb0
style: 이벤트 그리드 아이템 스타일 수정
khakhiD 363c26a
feat: 목업 데이터로 안내사항 추가, 캐치프레이즈 수정
khakhiD 3816cdd
style: 진행 중인 피드백 링크 데코레이션 underline 추가
khakhiD 6472802
Merge branch 'main' of https://github.com/resumeme/Frontend into GMMQ…
khakhiD a36aa10
fix: 탭 제목 (피드백 -> 이벤트) 수정
khakhiD File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
234 changes: 174 additions & 60 deletions
234
src/components/molecules/EventGridItem/EventGridItem.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,114 +1,228 @@ | ||
import { Text, Box, Image, HStack, Flex } from '@chakra-ui/react'; | ||
import { | ||
Text, | ||
Box, | ||
Image, | ||
HStack, | ||
Flex, | ||
Card, | ||
CardBody, | ||
Divider, | ||
CardFooter, | ||
Tooltip, | ||
} from '@chakra-ui/react'; | ||
import { Link } from 'react-router-dom'; | ||
import { v4 as uuidv4 } from 'uuid'; | ||
import { Avatar } from '~/components/atoms/Avatar'; | ||
import { BorderBox } from '~/components/atoms/BorderBox'; | ||
import { Badge } from '~/components/atoms/Badge'; | ||
import { Label } from '~/components/atoms/Label'; | ||
import { assets } from '~/config/assets'; | ||
import { appPaths } from '~/config/paths'; | ||
import CONSTANTS from '~/constants'; | ||
import { EventListItem } from '~/types/event/eventList'; | ||
import { EventStatus } from '~/types/eventStatus'; | ||
import { Position } from '~/types/position'; | ||
|
||
const THUMBNAILS = assets.thumbnail; | ||
|
||
const EventGridItem = ({ event: { info, mentorInfo } }: { event: EventListItem }) => { | ||
const openDate = new Date(info.timeInfo.openDateTime).toLocaleDateString(); | ||
const closeDate = new Date(info.timeInfo.closeDateTime).toLocaleDateString(); | ||
const isFullCount = info.currentApplicantCount === info.maximumCount; | ||
const srcKey = info.positions[0] || 'FRONT'; | ||
const thumbnailSrc = THUMBNAILS[srcKey as keyof typeof THUMBNAILS]; | ||
|
||
return ( | ||
<Link to={appPaths.eventDetail(info.id)}> | ||
<Box | ||
w={'full'} | ||
aspectRatio={3 / 4.5} | ||
<Card | ||
overflow={'hidden'} | ||
role="group" | ||
position={'relative'} | ||
> | ||
<Image | ||
src="https://i.pinimg.com/564x/97/7c/ad/977cad5f391fe80dc7aa4a8194c30e9e.jpg" | ||
alt="썸네일 이미지" | ||
borderTopRadius={'1rem'} | ||
height={'45%'} | ||
w={'full'} | ||
/> | ||
<BorderBox | ||
borderTop={'none'} | ||
borderTopRadius={0} | ||
h={'55%'} | ||
<Box | ||
overflow={'hidden'} | ||
borderTopRadius={'lg'} | ||
h={'35%'} | ||
> | ||
<Image | ||
src={thumbnailSrc} | ||
aspectRatio={3 / 2} | ||
objectFit={'cover'} | ||
_groupHover={{ | ||
transform: 'scale(120%)', | ||
transition: '.5s', | ||
}} | ||
/> | ||
</Box> | ||
<CardBody> | ||
<Flex | ||
direction={'column'} | ||
justifyContent={'space-between'} | ||
h={'full'} | ||
gap={'0.5rem'} | ||
flex={1} | ||
gap={2} | ||
> | ||
<AvatarAndStatus | ||
status={info.status} | ||
<Tooltip | ||
label={info.title} | ||
placement="top-start" | ||
fontSize={'xs'} | ||
fontWeight={'normal'} | ||
openDelay={500} | ||
bg={'white'} | ||
color={'gray.700'} | ||
hasArrow | ||
> | ||
<Text | ||
size="md" | ||
noOfLines={1} | ||
fontWeight={'bold'} | ||
color={'gray.700'} | ||
> | ||
{info.title} | ||
</Text> | ||
</Tooltip> | ||
<MentorInfo | ||
imageUrl={mentorInfo.imageUrl} | ||
nickname={mentorInfo.nickname} | ||
/> | ||
<Text | ||
// flex={1} | ||
h={'30%'} | ||
noOfLines={2} | ||
color={'gray.800'} | ||
> | ||
{info.title} | ||
</Text> | ||
</Flex> | ||
</CardBody> | ||
<Divider | ||
borderColor={'gray.300'} | ||
mx={'auto'} | ||
w={'95%'} | ||
/> | ||
<CardFooter> | ||
<Flex | ||
justify={'space-between'} | ||
w={'full'} | ||
> | ||
{/* FIXME 이벤트 대표 직무 1개로 변경하기 */} | ||
<PositionLabels positions={info.positions} /> | ||
<Flex | ||
justifyContent={'space-between'} | ||
flexWrap={'wrap'} | ||
<Label | ||
py={0} | ||
px={1.5} | ||
maxH={'1.3rem'} | ||
fontSize={'xs'} | ||
fontWeight={'medium'} | ||
bg={'gray.200'} | ||
color={'gray.500'} | ||
textDecoration={isFullCount ? 'line-through' : 'none'} | ||
> | ||
<Text fontSize={'0.875rem'}> | ||
{openDate} ~ {closeDate} | ||
</Text> | ||
<Text | ||
fontSize={'0.875rem'} | ||
>{`인원 ${info.currentApplicantCount}/${info.maximumCount}`}</Text> | ||
</Flex> | ||
{info.currentApplicantCount} / {info.maximumCount} | ||
</Label> | ||
</Flex> | ||
</BorderBox> | ||
</Box> | ||
</CardFooter> | ||
|
||
<Tooltip | ||
label={`${openDate} ~ ${closeDate}`} | ||
placement="top" | ||
fontSize={'sm'} | ||
fontWeight={'normal'} | ||
bg={'white'} | ||
color={'gray.700'} | ||
hasArrow | ||
> | ||
<Box | ||
position={'absolute'} | ||
top={'3%'} | ||
right={'3%'} | ||
zIndex={'docked'} | ||
> | ||
<StatusBadge status={info.status} /> | ||
</Box> | ||
</Tooltip> | ||
</Card> | ||
</Link> | ||
); | ||
}; | ||
|
||
export default EventGridItem; | ||
|
||
const AvatarAndStatus = ({ | ||
status, | ||
imageUrl, | ||
nickname, | ||
}: { | ||
status: EventStatus; | ||
imageUrl: string; | ||
nickname: string; | ||
}) => { | ||
const StatusBadge = ({ status }: { status: EventStatus }) => { | ||
const isActive = status === 'OPEN' || status === 'REOPEN'; | ||
|
||
return ( | ||
<Label | ||
bg={isActive ? 'green.500' : 'gray.300'} | ||
py={'0.1rem'} | ||
h={'fit-content'} | ||
color={isActive ? 'white' : 'gray.600'} | ||
fontWeight={'semibold'} | ||
> | ||
{CONSTANTS.EVENT_STATUS[status]} | ||
</Label> | ||
); | ||
}; | ||
|
||
const MentorInfo = ({ imageUrl, nickname }: { imageUrl: string; nickname: string }) => { | ||
return ( | ||
<Flex justifyContent={'space-between'}> | ||
<HStack> | ||
<Avatar | ||
src={imageUrl} | ||
w={'2rem'} | ||
h={'2rem'} | ||
w={'1.5rem'} | ||
h={'1.5rem'} | ||
/> | ||
<Text color={'gray.900'}>{nickname}</Text> | ||
<Text | ||
color={'gray.700'} | ||
fontSize={'sm'} | ||
fontWeight={'semibold'} | ||
noOfLines={1} | ||
> | ||
{nickname} | ||
</Text> | ||
<Badge | ||
type="mentee" | ||
fontSize={'xs'} | ||
fontWeight={'medium'} | ||
py={0} | ||
> | ||
멘토 | ||
</Badge> | ||
</HStack> | ||
<Label bg={isActive ? 'primary.900' : 'gray.400'}>{CONSTANTS.EVENT_STATUS[status]}</Label> | ||
</Flex> | ||
); | ||
}; | ||
|
||
const PositionLabels = ({ positions }: { positions: Position[] }) => { | ||
const MAX_LABELS_TO_DISPLAY = 1; | ||
|
||
return ( | ||
<Flex | ||
flexWrap={'wrap'} | ||
gap={'0.2rem'} | ||
> | ||
{positions.map((position) => ( | ||
<Flex gap={'0.2rem'}> | ||
{positions.slice(0, MAX_LABELS_TO_DISPLAY).map((position) => ( | ||
<Label | ||
key={uuidv4()} | ||
type={position} | ||
py={0} | ||
/> | ||
))} | ||
{positions.length > MAX_LABELS_TO_DISPLAY && ( | ||
<Tooltip | ||
placement="top" | ||
bg={'white'} | ||
rounded={'xl'} | ||
hasArrow | ||
label={ | ||
<Flex | ||
direction={'column'} | ||
align={'start'} | ||
> | ||
{positions.slice(MAX_LABELS_TO_DISPLAY).map((position) => ( | ||
<Label | ||
key={uuidv4()} | ||
w={'fit-content'} | ||
type={position} | ||
py={0} | ||
/> | ||
))} | ||
</Flex> | ||
} | ||
> | ||
<Text | ||
ml={1} | ||
fontSize={'xs'} | ||
color={'gray.500'} | ||
fontWeight={'semibold'} | ||
>{`+${positions.length - MAX_LABELS_TO_DISPLAY}`}</Text> | ||
</Tooltip> | ||
)} | ||
</Flex> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
positions를 직접 자르는것 보다 splice를 사용하는 것도 좋아보여요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
splice를 사용하면 원본 배열을 건드는 것으로 알고 있어서 slice를 사용했습니다.
혹시나 같은 컴포넌트에서 positions를 사용할 일이 있을 수도 있으니 허허... :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
반대로 알고 있었네요 ㅜㅜ