-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(my-recruit): 내 공고 페이지 카드 UI구현 (#22)
* feat(my-recruit): 내 공고 페이지 카드 UI구현 * update color * refactor
- Loading branch information
1 parent
aa45492
commit 1d72ffc
Showing
14 changed files
with
371 additions
and
0 deletions.
There are no files selected for viewing
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
68 changes: 68 additions & 0 deletions
68
src/app/(sidebar)/my-recruit/containers/components/Card/BoxCard.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 |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { Spacing } from '@/components/Spacing'; | ||
import { Icon } from '@/system/components'; | ||
import { color } from '@/system/token/color'; | ||
import { dday } from '@/utils/date'; | ||
import { MoreButton } from '@/app/(sidebar)/my-recruit/containers/components/Card/common/MoreButton'; | ||
import { StatusButton } from '@/app/(sidebar)/my-recruit/containers/components/Card/common/StatusButton'; | ||
import { Dialog } from '@/system/components/Dialog/ShadcnDialog'; | ||
import { DueDateDialog } from '../DueDateDialog'; | ||
|
||
export type ProgressingCardType = { | ||
type: '서류 마감' | '1차 면접' | '2차 면접'; | ||
status: '지원 완료' | '서류 통과' | '서류 탈락'; | ||
dueDate: Date | null; | ||
period: string; | ||
title: string; | ||
}; | ||
|
||
export function BoxCard({ type, title, status, dueDate, period }: ProgressingCardType) { | ||
return ( | ||
<div className="w-[320px] rounded-[10px] overflow-hidden cursor-pointer"> | ||
<div className="h-38 pr-12 pl-20 bg-neutral-95 flex justify-between items-center"> | ||
{dueDate == null ? ( | ||
<Dialog> | ||
<Dialog.Trigger className="flex justify-between items-center w-full"> | ||
<span className="text-label2 text-neutral-50">공고 일정을 등록해주세요</span> | ||
<Icon name="add" size={24} color={color.neutral50} /> | ||
</Dialog.Trigger> | ||
<Dialog.Content className="w-400"> | ||
<DueDateDialog title={title} /> | ||
</Dialog.Content> | ||
</Dialog> | ||
) : ( | ||
<> | ||
<div className="flex items-center gap-[4px]"> | ||
<Icon name="clover" size={20} color={color.mint30} /> | ||
<span className="text-white text-label2 "> | ||
{type} D-{dday(dueDate)} | ||
</span> | ||
</div> | ||
<MoreButton /> | ||
</> | ||
)} | ||
</div> | ||
<div className="p-20 pt-16 bg-white border-neutral-5 border-1 rounded-b-[10px] hover:border-neutral-95"> | ||
<div className="flex justify-between items-center"> | ||
<div className="bg-mint-1 text-mint-50 text-label1 px-8 py-4 rounded-4">{period}</div> | ||
<StatusButton currentStatus={status} /> | ||
</div> | ||
<Spacing size={16} /> | ||
<span className="text-nuetral-95 font-semibold font-body1 text-ellipsis line-clamp-1">{title}</span> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
const statusList = [ | ||
{ variant: 'text', text: '지원 준비' }, | ||
{ variant: 'text', text: '지원 완료' }, | ||
{ variant: 'border' }, | ||
{ variant: 'text', text: '서류 통과' }, | ||
{ variant: 'text', text: '서류 탈락' }, | ||
{ variant: 'border' }, | ||
{ variant: 'text', text: '면접 통과' }, | ||
{ variant: 'text', text: '면접 탈락' }, | ||
{ variant: 'border' }, | ||
{ variant: 'text', text: '최종 합격' }, | ||
{ variant: 'text', text: '최종 탈락' }, | ||
] as const; |
44 changes: 44 additions & 0 deletions
44
src/app/(sidebar)/my-recruit/containers/components/Card/RowCard.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 |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { If } from '@/components/If'; | ||
import { Spacing } from '@/components/Spacing'; | ||
import { Icon } from '@/system/components'; | ||
import { color } from '@/system/token/color'; | ||
import { dday } from '@/utils/date'; | ||
import { MoreButton } from '@/app/(sidebar)/my-recruit/containers/components/Card/common/MoreButton'; | ||
import { StatusButton } from './common/StatusButton'; | ||
|
||
interface RowCardProps { | ||
type: '서류 마감' | '1차 면접' | '2차 면접'; | ||
status: '지원 완료' | '서류 통과' | '서류 탈락'; | ||
dueDate: Date | null; | ||
period: string; | ||
title: string; | ||
} | ||
|
||
export function RowCard({ type, title, status, dueDate, period }: RowCardProps) { | ||
return ( | ||
<div className="rounded-[10px] overflow-hidden flex cursor-pointer"> | ||
<div className="w-12 bg-neutral-95" /> | ||
<div className="px-24 py-22 flex-1 flex items-center border-1 border-neutral-5 border-l-neutral-95 rounded-r-[10px] justify-between"> | ||
<div className="flex items-center"> | ||
<span className="text-neutral-50 text-label2 font-medium">{period}</span> | ||
<Spacing size={24} direction="row" /> | ||
<If condition={dueDate != null}> | ||
<div className="px-6 py-4 rounded-[4px] bg-neutral-95 flex gap-[2px]"> | ||
<Icon name="clover" size={20} color={color.mint30} /> | ||
<span className="text-white text-label2 "> | ||
{type} D-{dday(dueDate!)} | ||
</span> | ||
</div> | ||
</If> | ||
<Spacing size={12} direction="row" /> | ||
<span className="font-semibold font-body1">{title}</span> | ||
</div> | ||
<div className="flex items-center"> | ||
<StatusButton currentStatus={status} /> | ||
<Spacing size={32} direction="row" /> | ||
<MoreButton /> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
24 changes: 24 additions & 0 deletions
24
src/app/(sidebar)/my-recruit/containers/components/Card/common/MoreButton.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 |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { Icon } from '@/system/components'; | ||
import { | ||
DropdownMenu, | ||
DropdownMenuContent, | ||
DropdownMenuItem, | ||
DropdownMenuTrigger, | ||
} from '@/system/components/DropdownMenu/DropdownMenu'; | ||
import { color } from '@/system/token/color'; | ||
|
||
export function MoreButton() { | ||
return ( | ||
<DropdownMenu> | ||
<DropdownMenuTrigger className="outline-none"> | ||
<Icon name="more" size={24} color={color.neutral40} /> | ||
</DropdownMenuTrigger> | ||
<DropdownMenuContent> | ||
<DropdownMenuItem className="gap-[8px]"> | ||
<Icon name="delete" color="#FF5C5C" /> | ||
<div className="text-red-50 text-[15px] font-normal">삭제하기</div> | ||
</DropdownMenuItem> | ||
</DropdownMenuContent> | ||
</DropdownMenu> | ||
); | ||
} |
58 changes: 58 additions & 0 deletions
58
src/app/(sidebar)/my-recruit/containers/components/Card/common/StatusButton.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 |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { SwitchCase } from '@/components/SwitchCase'; | ||
import { Icon } from '@/system/components'; | ||
import { | ||
DropdownMenu, | ||
DropdownMenuContent, | ||
DropdownMenuItem, | ||
DropdownMenuTrigger, | ||
DropdownMenuSeparator, | ||
} from '@/system/components/DropdownMenu/DropdownMenu'; | ||
import { color } from '@/system/token/color'; | ||
import { cn } from '@/utils'; | ||
|
||
interface Props { | ||
currentStatus: string; | ||
} | ||
|
||
export function StatusButton({ currentStatus }: Props) { | ||
return ( | ||
<DropdownMenu> | ||
<DropdownMenuTrigger className="outline-none"> | ||
<div className="flex items-center"> | ||
<span className="text-label2 text-neutral-35">{currentStatus}</span> | ||
<Icon name="downChevron" color={color.neutral10} /> | ||
</div> | ||
</DropdownMenuTrigger> | ||
<DropdownMenuContent> | ||
{statusList.map((item) => ( | ||
<SwitchCase | ||
value={item.variant} | ||
caseBy={{ | ||
text: | ||
item.variant === 'text' ? ( | ||
<DropdownMenuItem className={cn(currentStatus === item.text ? 'text-neutral-30' : '')}> | ||
{item.text} | ||
</DropdownMenuItem> | ||
) : null, | ||
border: <DropdownMenuSeparator />, | ||
}} | ||
/> | ||
))} | ||
</DropdownMenuContent> | ||
</DropdownMenu> | ||
); | ||
} | ||
|
||
const statusList = [ | ||
{ variant: 'text', text: '지원 준비' }, | ||
{ variant: 'text', text: '지원 완료' }, | ||
{ variant: 'border' }, | ||
{ variant: 'text', text: '서류 통과' }, | ||
{ variant: 'text', text: '서류 탈락' }, | ||
{ variant: 'border' }, | ||
{ variant: 'text', text: '면접 통과' }, | ||
{ variant: 'text', text: '면접 탈락' }, | ||
{ variant: 'border' }, | ||
{ variant: 'text', text: '최종 합격' }, | ||
{ variant: 'text', text: '최종 탈락' }, | ||
] as const; |
64 changes: 64 additions & 0 deletions
64
src/app/(sidebar)/my-recruit/containers/components/DueDateDialog.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 |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { Spacing } from '@/components/Spacing'; | ||
import { Button, Icon } from '@/system/components'; | ||
import { color } from '@/system/token/color'; | ||
import clsx from 'clsx'; | ||
import { motion } from 'framer-motion'; | ||
import { Popover, PopoverContent, PopoverTrigger } from '@/system/components/Popover/Popover'; | ||
import { Calendar } from '@/system/components/Calendar/Calendar'; | ||
import { format } from 'date-fns/format'; | ||
import { useState } from 'react'; | ||
|
||
interface DueDateDialogProps { | ||
title: string; | ||
} | ||
|
||
export function DueDateDialog({ title }: DueDateDialogProps) { | ||
const [selectedDate, setSelectedDate] = useState<Date>(); | ||
|
||
const isDateSelected = selectedDate != null; | ||
|
||
return ( | ||
<div className="p-20"> | ||
<div className="flex items-center w-314"> | ||
<Icon name="folderFill" size={16} color={color.neutral95} /> | ||
<Spacing size={4} direction="row" /> | ||
<span className="text-body1 font-semibold flex-1 overflow-hidden text-ellipsis line-clamp-1">{title}</span> | ||
<span className="text-body1">의 공고 일정 등록하기</span> | ||
</div> | ||
<Spacing size={4} /> | ||
<span className="text-caption1 text-neutral-35">일정을 등록하면 잊지 않도록 알려드릴게요!</span> | ||
<Spacing size={24} /> | ||
{/* 마감일 입력 */} | ||
<div className="w-full flex justify-between items-center p-8 bg-neutral-1 rounded-[8px]"> | ||
<span className="text-label1 text-neutral-95">서류마감</span> | ||
<Popover> | ||
<PopoverTrigger> | ||
<motion.div | ||
initial="initial" | ||
variants={{ | ||
initial: { backgroundColor: 'rgb(241, 242, 243, 0)' }, | ||
touch: { scale: 0.96, transition: { duration: 0.1 } }, | ||
hover: { backgroundColor: 'rgb(241, 242, 243, 1)' }, | ||
}} | ||
whileTap="touch" | ||
whileHover="hover" | ||
className="px-8 py-4 flex items-center gap-[4px] rounded-[4px]"> | ||
<Icon name={isDateSelected ? 'calendarFill' : 'calendar'} size={20} color={color.neutral30} /> | ||
<span className={clsx('text-label2', isDateSelected ? 'text-neutral-95' : 'text-neutral-40')}> | ||
{isDateSelected ? format(selectedDate, 'yyyy.mm.dd') : '마감일을 선택해주세요'} | ||
</span> | ||
</motion.div> | ||
</PopoverTrigger> | ||
<PopoverContent className="w-200"> | ||
<Calendar mode="single" selected={selectedDate} onSelect={setSelectedDate} /> | ||
</PopoverContent> | ||
</Popover> | ||
</div> | ||
<Spacing size={16} /> | ||
<Button className="w-full h-46 flex justify-center items-center gap-[4px] border-[1px] border-neutral-35 border-dashed rounded-[6px]"> | ||
<Icon name="add" color={color.neutral35} /> | ||
<span className="text-caption1 font-medium text-neutral-35">일정 추가하기</span> | ||
</Button> | ||
</div> | ||
); | ||
} |
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 |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { ProgressingCardType } from './containers/components/Card/BoxCard'; | ||
|
||
export const cardList: ProgressingCardType[] = [ | ||
{ | ||
type: '1차 면접', | ||
status: '서류 통과', | ||
dueDate: null, | ||
period: '2024 상반기', | ||
title: '디프만 15기 디자이너 직군', | ||
}, | ||
{ | ||
type: '2차 면접', | ||
status: '지원 완료', | ||
dueDate: new Date('2024-08-20'), | ||
period: '2024 하반기', | ||
title: '2024 네이버 프로덕트 디자이너 신입공채 지원서 제출', | ||
}, | ||
]; |
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 |
---|---|---|
@@ -0,0 +1,17 @@ | ||
interface Props<Case extends string | number> { | ||
caseBy: Partial<Record<Case, JSX.Element | null>>; | ||
value: Case; | ||
defaultComponent?: JSX.Element | null; | ||
} | ||
|
||
export function SwitchCase<Case extends string | number>({ | ||
value, | ||
caseBy, | ||
defaultComponent: defaultComponent = null, | ||
}: Props<Case>) { | ||
if (value == null) { | ||
return defaultComponent; | ||
} | ||
|
||
return caseBy[value] ?? defaultComponent; | ||
} |
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.