diff --git a/.gitignore b/.gitignore index 03c19c1e..12ab66dc 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ yarn-error.log* # local env files .env*.local +.env # vercel .vercel diff --git a/src/apis/http.ts b/src/apis/http.ts index 0547ea80..b230ce27 100644 --- a/src/apis/http.ts +++ b/src/apis/http.ts @@ -1,4 +1,3 @@ -import { serverErrorType } from '@/types/api'; import { isProductionEnv } from '@/utils/common'; import type { AxiosError, @@ -47,11 +46,11 @@ axiosInstance.interceptors.response.use( async (error: AxiosError) => { if (axios.isAxiosError(error)) { - const data = error.response?.data as serverErrorType; + const status = error.response?.status; const refreshToken = getCookie('refreshToken'); - if (refreshToken) { - if (data?.status === 'UNAUTHORIZED') { + if (status === 401) { + if (refreshToken) { deleteCookie('accessToken'); deleteCookie('refreshToken'); try { @@ -62,6 +61,7 @@ axiosInstance.interceptors.response.use( window.location.href = '/login'; } } + window.location.href = '/login'; } } diff --git a/src/app/(sidebar)/my-recruit/[id]/api/useDeleteRecruit.ts b/src/app/(sidebar)/my-recruit/[id]/api/useDeleteRecruit.ts new file mode 100644 index 00000000..7647f6a7 --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/api/useDeleteRecruit.ts @@ -0,0 +1,16 @@ +import { http } from '@/apis/http'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +const deleteRecruit = (id: string) => { + return http.delete({ + url: `/recruits/${id}`, + }); +}; + +export const useDeleteRecruit = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: deleteRecruit, + }); +}; diff --git a/src/app/(sidebar)/my-recruit/[id]/api/useGetAllTag.ts b/src/app/(sidebar)/my-recruit/[id]/api/useGetAllTag.ts new file mode 100644 index 00000000..f18184ac --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/api/useGetAllTag.ts @@ -0,0 +1,21 @@ +import { http } from '@/apis/http'; +import { TagType } from '@/types'; +import { useSuspenseQuery } from '@tanstack/react-query'; + +const getAllTags = () => { + return http.get({ + url: `/tags`, + }); +}; + +export function useGetAllTags() { + const result = useSuspenseQuery({ + queryKey: ['get-all-tags'], + queryFn: async () => { + const res = await getAllTags(); + return res.data; + }, + }); + + return result; +} diff --git a/src/app/(sidebar)/my-recruit/[id]/api/useGetCardCount.ts b/src/app/(sidebar)/my-recruit/[id]/api/useGetCardCount.ts new file mode 100644 index 00000000..1ccc81d1 --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/api/useGetCardCount.ts @@ -0,0 +1,22 @@ +import { http } from '@/apis/http'; +import { useSuspenseQuery } from '@tanstack/react-query'; + +type getCardCountType = Record<'서류_준비' | '과제_준비' | '인터뷰_준비', number>; + +const getCardCount = (id: string) => { + return http.get({ + url: `/recruits/${id}/cards/type-count`, + }); +}; + +export function useGetCardCount(id: string) { + const result = useSuspenseQuery({ + queryKey: ['get-progress-recruit'], + queryFn: async () => { + const res = await getCardCount(id); + return res.data; + }, + }); + + return result; +} diff --git a/src/app/(sidebar)/my-recruit/[id]/api/useGetProgressRecruit.ts b/src/app/(sidebar)/my-recruit/[id]/api/useGetProgressRecruit.ts new file mode 100644 index 00000000..0b60e5a3 --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/api/useGetProgressRecruit.ts @@ -0,0 +1,35 @@ +import { http } from '@/apis/http'; +import { useSuspenseQuery } from '@tanstack/react-query'; + +export interface NearestScheduleType { + id: number; + recruitScheduleStage: string; + deadLine: string; +} +export interface ProgressRecruitType { + id: number; + title: string; + season: string; + siteUrl: string; + recruitStatus: string; + createdDate: string; + nearestSchedule: NearestScheduleType | null; +} + +const getProgressRecruit = () => { + return http.get({ + url: `/recruits/progressing`, + }); +}; + +export function useGetProgressRecruit() { + const result = useSuspenseQuery({ + queryKey: ['get-progress-recruit'], + queryFn: async () => { + const res = await getProgressRecruit(); + return res.data; + }, + }); + + return result; +} diff --git a/src/app/(sidebar)/my-recruit/[id]/api/useGetRecruitById.ts b/src/app/(sidebar)/my-recruit/[id]/api/useGetRecruitById.ts new file mode 100644 index 00000000..f7328041 --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/api/useGetRecruitById.ts @@ -0,0 +1,28 @@ +import { http } from '@/apis/http'; +import { useSuspenseQuery } from '@tanstack/react-query'; + +interface recruitByIdType { + id: number; + title: string; + season: string; + siteUrl: string; + recruitStatus: string; +} + +const getRecruitById = (id: string) => { + return http.get({ + url: `/recruits/${id}`, + }); +}; + +export function useGetRecruitById(id: string) { + const result = useSuspenseQuery({ + queryKey: ['get-recruit-by-id', id], + queryFn: async () => { + const res = await getRecruitById(id); + return res.data; + }, + }); + + return result; +} diff --git a/src/app/(sidebar)/my-recruit/[id]/api/useGetRecruitCards.ts b/src/app/(sidebar)/my-recruit/[id]/api/useGetRecruitCards.ts new file mode 100644 index 00000000..3793fe15 --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/api/useGetRecruitCards.ts @@ -0,0 +1,28 @@ +import { http } from '@/apis/http'; +import { TagType } from '@/types'; +import { useSuspenseQuery } from '@tanstack/react-query'; + +export type GetRecruitCardsType = { + id: number; + title: string; + updatedDate: string; + tagList: TagType[]; +}; + +const getRecruitCards = ({ id, progress }: { id: string; progress: string }) => { + return http.get({ + url: `recruits/${id}/cards?type=${progress}`, + }); +}; + +export function useGetRecruitCards({ id, progress }: { id: string; progress: string }) { + const result = useSuspenseQuery({ + queryKey: ['get-recruit-card-id', id, progress], + queryFn: async () => { + const res = await getRecruitCards({ id, progress }); + return res.data; + }, + }); + + return result; +} diff --git a/src/app/(sidebar)/my-recruit/[id]/api/useGetSeason.ts b/src/app/(sidebar)/my-recruit/[id]/api/useGetSeason.ts new file mode 100644 index 00000000..c86bf8b0 --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/api/useGetSeason.ts @@ -0,0 +1,24 @@ +import { http } from '@/apis/http'; +import { useSuspenseQuery } from '@tanstack/react-query'; + +export interface SeasonType { + name: string; +} + +const getSeasons = () => { + return http.get({ + url: `/seasons`, + }); +}; + +export function useGetSeasons() { + const result = useSuspenseQuery({ + queryKey: ['get-seasons'], + queryFn: async () => { + const res = await getSeasons(); + return res.data; + }, + }); + + return result; +} diff --git a/src/app/(sidebar)/my-recruit/[id]/api/usePatchSeason.ts b/src/app/(sidebar)/my-recruit/[id]/api/usePatchSeason.ts new file mode 100644 index 00000000..07a5a4d0 --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/api/usePatchSeason.ts @@ -0,0 +1,32 @@ +import { http } from '@/apis/http'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { ProgressRecruitType } from './useGetProgressRecruit'; + +interface PatchSeasonProps { + newSeason: string; + id: string; +} + +const patchSeason = ({ newSeason, id }: PatchSeasonProps) => { + return http.patch({ + url: `/recruits/${id}/season`, + data: { + season: newSeason, + }, + }); +}; + +export const usePatchSeason = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async ({ newSeason, id }: PatchSeasonProps) => { + const res = await patchSeason({ newSeason, id }); + + return res.data; + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['get-recruit-by-id'] }); + }, + }); +}; diff --git a/src/app/(sidebar)/my-recruit/[id]/api/usePatchSiteUrl.ts b/src/app/(sidebar)/my-recruit/[id]/api/usePatchSiteUrl.ts new file mode 100644 index 00000000..ee2b6bfb --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/api/usePatchSiteUrl.ts @@ -0,0 +1,32 @@ +import { http } from '@/apis/http'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { ProgressRecruitType } from './useGetProgressRecruit'; + +interface patchSiteProps { + newSiteUrl: string; + id: string; +} + +const patchSiteUrl = ({ newSiteUrl, id }: patchSiteProps) => { + return http.patch({ + url: `/recruits/${id}/siteUrl`, + data: { + siteUrl: newSiteUrl, + }, + }); +}; + +export const usePatchSiteUrl = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async ({ newSiteUrl, id }: patchSiteProps) => { + const res = await patchSiteUrl({ newSiteUrl, id }); + + return res.data; + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['get-recruit-by-id'] }); + }, + }); +}; diff --git a/src/app/(sidebar)/my-recruit/[id]/api/usePatchStatus.ts b/src/app/(sidebar)/my-recruit/[id]/api/usePatchStatus.ts new file mode 100644 index 00000000..7704680e --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/api/usePatchStatus.ts @@ -0,0 +1,37 @@ +import { http } from '@/apis/http'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +interface PatchStatusResponse { + status: string; +} + +interface patchStatusProps { + newStatus: string; + id: string; +} + +const patchStatus = ({ newStatus, id }: patchStatusProps) => { + return http.patch({ + url: `/recruits/${id}/status`, + data: { + recruitStatus: newStatus, + }, + }); +}; + +export const usePatchStatus = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async ({ newStatus, id }: patchStatusProps) => { + const res = await patchStatus({ newStatus, id }); + + console.log(res); + + return res.data; + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['get-recruit-by-id'] }); + }, + }); +}; diff --git a/src/app/(sidebar)/my-recruit/[id]/api/usePatchTitle.ts b/src/app/(sidebar)/my-recruit/[id]/api/usePatchTitle.ts new file mode 100644 index 00000000..4d9b039a --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/api/usePatchTitle.ts @@ -0,0 +1,35 @@ +import { http } from '@/apis/http'; +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +interface PatchTitleResponse { + title: string; +} + +interface patchTitleProps { + newTitle: string; + id: string; +} + +const patchTitle = ({ newTitle, id }: patchTitleProps) => { + return http.patch({ + url: `/recruits/${id}/title`, + data: { + title: newTitle, + }, + }); +}; + +export const usePatchTitle = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async ({ newTitle, id }: patchTitleProps) => { + const res = await patchTitle({ newTitle, id }); + + return res.data; + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['get-recruit-by-id'] }); + }, + }); +}; diff --git a/src/app/(sidebar)/my-recruit/[id]/components/ApplicationStatus.tsx b/src/app/(sidebar)/my-recruit/[id]/components/ApplicationStatus.tsx new file mode 100644 index 00000000..087a4805 --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/components/ApplicationStatus.tsx @@ -0,0 +1,64 @@ +import { Dropdown, Icon } from '@/system/components'; +import { DropdownMenuSeparator } from '@/system/components/DropdownMenu/DropdownMenu'; +import { color } from '@/system/token/color'; +import { SwitchCase } from '@/system/utils/SwitchCase'; +import { cn } from '@/utils'; +import { useState } from 'react'; +import { usePatchStatus } from '../api/usePatchStatus'; + +export function ApplicationStatus({ recruitId, status }: { recruitId: string; status: string }) { + const [clickStatus, setClickStatus] = useState(status); + + const { mutate: patchStatus } = usePatchStatus(); + + const handlePatchStatus = (status: string) => { + setClickStatus(status); + patchStatus({ newStatus: status, id: recruitId }); + }; + + return ( + + +
+ {clickStatus} + +
+
+ + {statusList.map((item, index) => ( + handlePatchStatus(item.text)} + //NOTE text-neutral-50 컬러 안먹힘 확인필요 + className={cn(clickStatus === item.text ? 'text-[#AEB0B8] flex justify-between' : '')}> + {item.text} + {clickStatus === item.text && } + + ) : null, + border: , + }} + /> + ))} + +
+ ); +} + +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; diff --git a/src/app/(sidebar)/my-recruit/[id]/components/DetailContent.tsx b/src/app/(sidebar)/my-recruit/[id]/components/DetailContent.tsx new file mode 100644 index 00000000..dfb4dc6b --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/components/DetailContent.tsx @@ -0,0 +1,87 @@ +'use client'; + +import { InfoCard } from '@/components/InfoCard'; +import { Icon } from '@/system/components'; +import { color } from '@/system/token/color'; +import { InfoCardType } from '@/types'; +import { cn } from '@/utils/tailwind-util'; +import Link from 'next/link'; +import { useState } from 'react'; +import { useGetAllTags } from '../api/useGetAllTag'; +import { useGetCardCount } from '../api/useGetCardCount'; +import { useGetRecruitCards } from '../api/useGetRecruitCards'; +import TagList from './TagList'; + +const PROGRESS_OPTIONS = ['서류_준비', '과제_준비', '인터뷰_준비'] as const; + +export type ProgressType = (typeof PROGRESS_OPTIONS)[number]; + +export function DetailContent({ recruitId }: { recruitId: string }) { + const [currentOption, setCurrentOption] = useState('서류_준비'); + const [selectedTags, setSelectedTags] = useState([]); + + const { data: cardCount } = useGetCardCount(recruitId); + const { data: tagsData } = useGetAllTags(); + const { data: cardList } = useGetRecruitCards({ id: recruitId, progress: currentOption }); + + const filteredCardList = + selectedTags.length > 0 + ? cardList?.filter((card) => card.tagList.some((tag) => selectedTags.includes(tag.name))) + : cardList; + + return ( +
+
+
+ {PROGRESS_OPTIONS.map((option) => { + const isActive = currentOption === option; + + return ( + + ); + })} +
+ + + +
카드 추가
+ +
+ + + +
+ {filteredCardList && filteredCardList.length > 0 ? ( +
    + {filteredCardList.map((info: InfoCardType) => ( +
  • + +
  • + ))} +
+ ) : ( +
+ +

아직 생성된 정보 카드가 없어요!

+
+ )} +
+
+ ); +} diff --git a/src/app/(sidebar)/my-recruit/[id]/components/DetailHeader.tsx b/src/app/(sidebar)/my-recruit/[id]/components/DetailHeader.tsx new file mode 100644 index 00000000..955ea986 --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/components/DetailHeader.tsx @@ -0,0 +1,84 @@ +'use client'; + +import { useOutsideClick } from '@/hooks/useOutsideClick'; +import { Button, Icon } from '@/system/components'; +import { color } from '@/system/token/color'; +import { cn } from '@/utils'; +import { ChangeEvent, useRef, useState } from 'react'; +import { useGetRecruitById } from '../api/useGetRecruitById'; +import { usePatchTitle } from '../api/usePatchTitle'; +import { ApplicationStatus } from './ApplicationStatus'; +import SemesterSelector from './SemesterSelector'; +import TextBubble from './TextBubble'; + +export default function DetailHeader({ recruitId }: { recruitId: string }) { + const { mutate: patchTitle } = usePatchTitle(); + const { data: recruitInfoById } = useGetRecruitById(recruitId); + + const tooltipRef = useRef(null); + const [title, setTitle] = useState(recruitInfoById?.title || ''); + const [isFocused, setIsFocused] = useState(false); + const [isHovered, setIsHovered] = useState(false); + const [isLinked, setIsLinked] = useState(false); + + useOutsideClick(tooltipRef, () => setIsLinked(false)); + + const handleTitleChange = (e: ChangeEvent) => { + setTitle(e.target.value); + }; + + const handleSetLink = () => { + setIsLinked(true); + setIsHovered(false); + }; + let timeoutId: NodeJS.Timeout | null = null; + + const handleMouseEnter = () => { + if (timeoutId) { + clearTimeout(timeoutId); + timeoutId = null; + } + setIsHovered(true); + }; + + const handleMouseLeave = () => { + timeoutId = setTimeout(() => { + setIsHovered(false); + }, 2000); + }; + + const handleUpdateTitle = () => { + setIsFocused(false); + patchTitle({ newTitle: title, id: recruitId }); + }; + + return ( +
+ + + setIsFocused(true)} + onBlur={handleUpdateTitle} + /> + +
+ {!isFocused && ( + + )} + +
+
+ ); +} diff --git a/src/app/(sidebar)/my-recruit/[id]/components/SemesterSelector.tsx b/src/app/(sidebar)/my-recruit/[id]/components/SemesterSelector.tsx new file mode 100644 index 00000000..a648b813 --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/components/SemesterSelector.tsx @@ -0,0 +1,48 @@ +import { Dropdown, Icon } from '@/system/components'; +import { color } from '@/system/token/color'; +import { cn } from '@/utils'; +import { Key, useState } from 'react'; +import { SeasonType, useGetSeasons } from '../api/useGetSeason'; +import { usePatchSeason } from '../api/usePatchSeason'; + +export default function SemesterSelector({ recruitId, season }: { recruitId: string; season: string }) { + const { data: seasons } = useGetSeasons(); + const { mutate: patchSeason } = usePatchSeason(); + + const [clickSemester, setClickSemester] = useState(season); + + const handlePatchStatus = (status: string) => { + setClickSemester(status); + patchSeason({ newSeason: status, id: recruitId }); + }; + + return ( + + +
+

{clickSemester}

+ + + +
+
+ + {seasons && + seasons.map((item: SeasonType, index: Key) => ( + { + handlePatchStatus(item.name); + }}> + {item.name} + {clickSemester === item.name && } + + ))} + +
+ ); +} diff --git a/src/app/(sidebar)/my-recruit/[id]/components/TagList.tsx b/src/app/(sidebar)/my-recruit/[id]/components/TagList.tsx new file mode 100644 index 00000000..bd81f974 --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/components/TagList.tsx @@ -0,0 +1,154 @@ +import { TagSelector } from '@/app/(sidebar)/write/[id]/components/TagSelector/TagSelector'; +import { Button, ButtonProps, Icon } from '@/system/components'; +import { color } from '@/system/token/color'; +import { If } from '@/system/utils/If'; +import { StrictPropsWithChildren, TagType } from '@/types'; +import { cn } from '@/utils'; +import { useEffect, useRef, useState } from 'react'; +import { TAG_TYPE_COLOR, colorStyle } from '../mocks'; + +interface TagListProps { + tagsData: TagType[]; + selectedTags: string[]; + setSelectedTags: (tags: string[]) => void; +} + +export default function TagList({ tagsData, selectedTags, setSelectedTags }: TagListProps) { + const tagContainerRef = useRef(null); + const [tags, setTags] = useState(tagsData || []); + + const [isOverflowing, setIsOverflowing] = useState(true); + const [viewAllTags, setViewAllTags] = useState(false); + + const handleTagClick = (name: string) => { + const clickedTag = tags.find((tag) => tag.name === name); + + if (clickedTag) { + const updatedTags = [clickedTag, ...tags.filter((tag) => tag.name !== name)]; + setTags(updatedTags); + + if (selectedTags.includes(name)) { + setSelectedTags(selectedTags.filter((selectedName) => selectedName !== name)); + } else { + setSelectedTags([...selectedTags, name]); + } + } + }; + + const checkOverflow = () => { + const container = tagContainerRef.current; + if (container) { + const isOverflow = + container.scrollHeight > container.clientHeight || container.scrollWidth > container.clientWidth; + setIsOverflowing(isOverflow); + } + }; + + useEffect(() => { + checkOverflow(); + + window.addEventListener('resize', checkOverflow); + return () => { + window.removeEventListener('resize', checkOverflow); + }; + }, []); + + return ( +
+
+ +
+ {viewAllTags ? ( + <> + + +
+ +
+

원하는 태그로 필터링 해보세요

+ +
+
+ + {tagsData && + tagsData.map((tag) => ( + handleTagClick(tag.name)}> + {tag.name} + + ))} + +
+
+
+ + ) : ( +
+ {selectedTags.length > 0 && ( + + )} + {tags && + tags.map((tag) => ( + handleTagClick(tag.name)}> + {tag.name} + + ))} + + + +
+ )} +
+
+ + + +
+
+
+ ); +} + +function Tag({ className, ...props }: StrictPropsWithChildren) { + return ( + + +
+
+
+
+ ); +} diff --git a/src/app/(sidebar)/my-recruit/[id]/mocks.ts b/src/app/(sidebar)/my-recruit/[id]/mocks.ts new file mode 100644 index 00000000..e8fba7f4 --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/mocks.ts @@ -0,0 +1,759 @@ +import { TagColor } from '@/system/components'; +import { InfoCardType, TagType } from '@/types'; + +export const mockInfoCount = { + '서류 준비': 16, + '과제 준비': 7, + '면접 준비': 4, +}; + +export const mockInfoList: InfoCardType[] = [ + { + id: 1, + title: '제목 입력 제목 입력 제목 입력 제목 입력 제목 입력 제목 입력 제목 입력 제목 입력 제목 입력 ', + updatedDate: '2024-07-20T20:00:00', + tagList: [ + { + id: 1, + name: '직무태그', + type: '인성', + }, + { + id: 2, + name: '역량태그1', + type: '역량', + }, + ], + }, + { + id: 2, + title: 'test title2', + updatedDate: '2024-07-10T20:00:00', + tagList: [ + { + id: 1, + name: '인성태그1', + type: '인성', + }, + { + id: 2, + name: '역량태그1', + type: '역량', + }, + ], + }, + { + id: 3, + title: '제목제목제목제목제목제목제목제목제목제목제목제목제목제목제목제목제목', + updatedDate: '2024-07-15T20:00:00', + tagList: [ + { + id: 1, + name: '인성태그1', + type: '인성', + }, + { + id: 2, + name: '역량태그1', + type: '역량', + }, + ], + }, + { + id: 4, + title: '제목4 제목4 제목4 제목4 제목4 제목4 제목4 제목4 제목4 제목4', + updatedDate: '2024-07-18T20:00:00', + tagList: [ + { + id: 1, + name: '직무태그2', + type: '인성', + }, + { + id: 2, + name: '역량태그2', + type: '역량', + }, + ], + }, + { + id: 5, + title: 'test title5', + updatedDate: '2024-07-19T20:00:00', + tagList: [ + { + id: 1, + name: '인성태그2', + type: '인성', + }, + { + id: 2, + name: '역량태그2', + type: '역량', + }, + ], + }, + { + id: 6, + title: '제목6 제목6 제목6 제목6 제목6 제목6 제목6 제목6 제목6', + updatedDate: '2024-07-17T20:00:00', + tagList: [ + { + id: 1, + name: '직무태그3', + type: '인성', + }, + { + id: 2, + name: '역량태그3', + type: '역량', + }, + ], + }, + { + id: 7, + title: '제목7 제목7 제목7 제목7 제목7 제목7 제목7 제목7 제목7', + updatedDate: '2024-07-21T20:00:00', + tagList: [ + { + id: 1, + name: '인성태그3', + type: '인성', + }, + { + id: 2, + name: '역량태그3', + type: '역량', + }, + ], + }, + { + id: 8, + title: 'test title8', + updatedDate: '2024-07-22T20:00:00', + tagList: [ + { + id: 1, + name: '직무태그4', + type: '인성', + }, + { + id: 2, + name: '역량태그4', + type: '역량', + }, + ], + }, + { + id: 9, + title: '제목9 제목9 제목9 제목9 제목9 제목9 제목9 제목9 제목9', + updatedDate: '2024-07-23T20:00:00', + tagList: [ + { + id: 1, + name: '인성태그4', + type: '인성', + }, + { + id: 2, + name: '역량태그4', + type: '역량', + }, + ], + }, + { + id: 10, + title: '제목10 제목10 제목10 제목10 제목10 제목10 제목10 제목10 제목10', + updatedDate: '2024-07-24T20:00:00', + tagList: [ + { + id: 1, + name: '직무태그5', + type: '인성', + }, + { + id: 2, + name: '역량태그5', + type: '역량', + }, + ], + }, + { + id: 11, + title: 'test title11', + updatedDate: '2024-07-25T20:00:00', + tagList: [ + { + id: 1, + name: '인성태그5', + type: '인성', + }, + { + id: 2, + name: '역량태그5', + type: '역량', + }, + ], + }, + { + id: 12, + title: '제목12 제목12 제목12 제목12 제목12 제목12 제목12 제목12 제목12', + updatedDate: '2024-07-26T20:00:00', + tagList: [ + { + id: 1, + name: '직무태그6', + type: '인성', + }, + { + id: 2, + name: '역량태그6', + type: '역량', + }, + ], + }, + { + id: 13, + title: '제목13 제목13 제목13 제목13 제목13 제목13 제목13 제목13 제목13', + updatedDate: '2024-07-27T20:00:00', + tagList: [ + { + id: 1, + name: '인성태그6', + type: '인성', + }, + { + id: 2, + name: '역량태그6', + type: '역량', + }, + ], + }, + { + id: 14, + title: 'test title14', + updatedDate: '2024-07-28T20:00:00', + tagList: [ + { + id: 1, + name: '직무태그7', + type: '인성', + }, + { + id: 2, + name: '역량태그7', + type: '역량', + }, + ], + }, + { + id: 15, + title: '제목15 제목15 제목15 제목15 제목15 제목15 제목15 제목15 제목15', + updatedDate: '2024-07-29T20:00:00', + tagList: [ + { + id: 1, + name: '인성태그7', + type: '인성', + }, + { + id: 2, + name: '역량태그7', + type: '역량', + }, + ], + }, + { + id: 16, + title: 'test title16', + updatedDate: '2024-07-30T20:00:00', + tagList: [ + { + id: 1, + name: '직무태그8', + type: '인성', + }, + { + id: 2, + name: '역량태그8', + type: '역량', + }, + ], + }, + { + id: 17, + title: '제목17 제목17 제목17 제목17 제목17 제목17 제목17 제목17 제목17', + updatedDate: '2024-07-31T20:00:00', + tagList: [ + { + id: 1, + name: '인성태그8', + type: '인성', + }, + { + id: 2, + name: '역량태그8', + type: '역량', + }, + ], + }, + { + id: 18, + title: '제목18 제목18 제목18 제목18 제목18 제목18 제목18 제목18 제목18', + updatedDate: '2024-08-01T20:00:00', + tagList: [ + { + id: 1, + name: '직무태그9', + type: '인성', + }, + { + id: 2, + name: '역량태그9', + type: '역량', + }, + ], + }, + { + id: 19, + title: 'test title19', + updatedDate: '2024-08-02T20:00:00', + tagList: [ + { + id: 1, + name: '인성태그9', + type: '인성', + }, + { + id: 2, + name: '역량태그9', + type: '역량', + }, + ], + }, + { + id: 20, + title: '제목20 제목20 제목20 제목20 제목20 제목20 제목20 제목20 제목20', + updatedDate: '2024-08-03T20:00:00', + tagList: [ + { + id: 1, + name: '직무태그10', + type: '인성', + }, + { + id: 2, + name: '역량태그10', + type: '역량', + }, + ], + }, + { + id: 21, + title: 'test title21', + updatedDate: '2024-08-04T20:00:00', + tagList: [ + { + id: 1, + name: '인성태그10', + type: '인성', + }, + { + id: 2, + name: '역량태그10', + type: '역량', + }, + ], + }, + { + id: 22, + title: '제목22 제목22 제목22 제목22 제목22 제목22 제목22 제목22 제목22', + updatedDate: '2024-08-05T20:00:00', + tagList: [ + { + id: 1, + name: '직무태그11', + type: '인성', + }, + { + id: 2, + name: '역량태그11', + type: '역량', + }, + ], + }, + { + id: 23, + title: '제목23 제목23 제목23 제목23 제목23 제목23 제목23 제목23 제목23', + updatedDate: '2024-08-06T20:00:00', + tagList: [ + { + id: 1, + name: '인성태그11', + type: '인성', + }, + { + id: 2, + name: '역량태그11', + type: '역량', + }, + ], + }, + { + id: 24, + title: 'test title24', + updatedDate: '2024-08-07T20:00:00', + tagList: [ + { + id: 1, + name: '직무태그12', + type: '인성', + }, + { + id: 2, + name: '역량태그12', + type: '역량', + }, + ], + }, + { + id: 25, + title: '제목25 제목25 제목25 제목25 제목25 제목25 제목25 제목25 제목25', + updatedDate: '2024-08-08T20:00:00', + tagList: [ + { + id: 1, + name: '인성태그12', + type: '인성', + }, + { + id: 2, + name: '역량태그12', + type: '역량', + }, + ], + }, +]; + +export const TAG_MOCKS: TagType[] = [ + { + id: 1, + name: '커뮤니케이션', + type: '역량', + }, + { + id: 2, + name: '리더십', + type: '인성', + }, + { + id: 3, + name: '봉사활동', + type: '인성', + }, + { + id: 4, + name: '문제 해결 능력', + type: '역량', + }, + { + id: 5, + name: '팀워크', + type: '인성', + }, + { + id: 6, + name: '시각화', + type: '역량', + }, + { + id: 7, + name: '프로젝트 관리', + type: '역량', + }, + { + id: 8, + name: '창의력', + type: '역량', + }, + { + id: 9, + name: '대인관계', + type: '인성', + }, + { + id: 10, + name: '의사결정', + type: '역량', + }, + { + id: 11, + name: '어바웃타임', + type: '인성', + }, + { + id: 12, + name: '프로그래밍', + type: '역량', + }, + { + id: 13, + name: '주도성', + type: '인성', + }, + { + id: 14, + name: '프로그래밍', + type: '역량', + }, + { + id: 15, + name: '설득력', + type: '인성', + }, + { + id: 16, + name: '협상 기술', + type: '역량', + }, + { + id: 17, + name: '문서 작성', + type: '역량', + }, + { + id: 18, + name: '열정', + type: '인성', + }, + { + id: 19, + name: '비판적 사고', + type: '역량', + }, + { + id: 20, + name: '갈등 관리', + type: '인성', + }, + { + id: 21, + name: '의사소통 능력', + type: '역량', + }, + { + id: 22, + name: '책임감', + type: '인성', + }, + { + id: 23, + name: '정보 처리 능력', + type: '역량', + }, + { + id: 24, + name: '신뢰성', + type: '인성', + }, + { + id: 25, + name: '디자인 사고', + type: '역량', + }, + { + id: 26, + name: '자기 개발', + type: '인성', + }, + { + id: 27, + name: '자원 관리', + type: '역량', + }, +]; + +export const TAG_TYPE_COLOR: Record = { + 역량: 'blue', + 인성: 'purple', +}; + +export const colorStyle = { + default: 'bg-[#F1F2F3] text-[#37383C]', + blue: 'bg-[#E8F1FF] text-[#418CC3]', + purple: 'bg-[#F1E8FF] text-[#9C6BB3]', +}; + +export const DEFAULT_TAG_MOCKS: TagType[] = [ + { + id: 0, + name: '인성태그', + type: '인성', + }, + { + id: 1, + name: '역량태그', + type: '역량', + }, + { + id: 2, + name: '인성태그', + type: '인성', + }, + { + id: 3, + name: '역량태그', + type: '역량', + }, + { + id: 4, + name: '인성태그', + type: '인성', + }, + { + id: 5, + name: '역량태그', + type: '역량', + }, + { + id: 6, + name: '인성태그', + type: '인성', + }, + { + id: 7, + name: '역량태그', + type: '역량', + }, + { + id: 8, + name: '인성태그', + type: '인성', + }, + { + id: 9, + name: '역량태그', + type: '역량', + }, + { + id: 10, + name: '인성태그', + type: '인성', + }, + { + id: 11, + name: '역량태그', + type: '역량', + }, + { + id: 12, + name: '인성태그', + type: '인성', + }, + { + id: 13, + name: '역량태그', + type: '역량', + }, + { + id: 14, + name: '인성태그', + type: '인성', + }, + { + id: 15, + name: '역량태그', + type: '역량', + }, + { + id: 16, + name: '인성태그', + type: '인성', + }, + { + id: 17, + name: '역량태그', + type: '역량', + }, + { + id: 18, + name: '인성태그', + type: '인성', + }, + { + id: 19, + name: '역량태그', + type: '역량', + }, + { + id: 20, + name: '인성태그', + type: '인성', + }, + { + id: 21, + name: '역량태그', + type: '역량', + }, + { + id: 22, + name: '인성태그', + type: '인성', + }, + { + id: 23, + name: '역량태그', + type: '역량', + }, + { + id: 24, + name: '인성태그', + type: '인성', + }, + { + id: 25, + name: '역량태그', + type: '역량', + }, + { + id: 26, + name: '인성태그', + type: '인성', + }, + { + id: 27, + name: '역량태그', + type: '역량', + }, + { + id: 28, + name: '인성태그', + type: '인성', + }, + { + id: 29, + name: '역량태그', + type: '역량', + }, + { + id: 30, + name: '인성태그', + type: '인성', + }, + { + id: 31, + name: '역량태그', + type: '역량', + }, + { + id: 32, + name: '인성태그', + type: '인성', + }, +]; + +export const categoryTags = [ + { value: '서류 준비', type: 'category' }, + { value: '과제 준비', type: 'category' }, + { value: '면접 준비', type: 'category' }, +] as const; diff --git a/src/app/(sidebar)/my-recruit/[id]/page.tsx b/src/app/(sidebar)/my-recruit/[id]/page.tsx new file mode 100644 index 00000000..95e3275f --- /dev/null +++ b/src/app/(sidebar)/my-recruit/[id]/page.tsx @@ -0,0 +1,96 @@ +'use client'; + +import { InfoCard } from '@/components/InfoCard'; +import { AsyncBoundaryWithQuery } from '@/lib'; +import { DndContextWithOverlay } from '@/lib/dnd-kit/DndContextWithOverlay'; +import { Dropdown, Icon } from '@/system/components'; +import { color } from '@/system/token/color'; +import { cn } from '@/utils'; +import { DragEndEvent } from '@dnd-kit/core'; +import { AnimatePresence } from 'framer-motion'; +import { useRouter } from 'next/navigation'; +import { useState } from 'react'; +import { usePostCardToRecruit } from '../api/usePostCardToRecruit'; +import { RightSidebar } from '../containers/RightSidebar/RightSidebar'; +import { DueDateDialog } from '../containers/components/DueDateDialog'; +import { useDeleteRecruit } from './api/useDeleteRecruit'; +import { DetailContent } from './components/DetailContent'; +import DetailHeader from './components/DetailHeader'; + +export default function CompanyDetail({ params: { id: recruitId } }: { params: { id: string } }) { + const [sidebarOpened, setSidebarOpened] = useState(false); + const { mutate: deleteRecruit } = useDeleteRecruit(); + const { mutate: mutatePostCardToRecruit } = usePostCardToRecruit(); + const router = useRouter(); + + const handleDeleteRecruit = () => { + deleteRecruit(recruitId); + router.push('/my-recruit'); + }; + + const onDragEnd = ({ over, active }: DragEndEvent) => { + if (over == null || active == null || typeof over.id !== 'number' || typeof active.id !== 'number') { + return; + } + mutatePostCardToRecruit({ recruitId: over.id, cardId: active.id }); + }; + + return ( + + +
+
+
+
+ + +
+ + +
+ +
+
+ + + {}} /> + + +
+ + + + + +
+ +
+
+ + +
+ +
삭제하기
+
+
+
+
+
+
+ +
+ + {sidebarOpened ? setSidebarOpened(false)} /> : null} + +
+
+
+ ); +} diff --git a/src/app/(sidebar)/my-recruit/containers/AllRecruitment/AllRecruitment.tsx b/src/app/(sidebar)/my-recruit/containers/AllRecruitment/AllRecruitment.tsx index cc4b4669..69e362a8 100644 --- a/src/app/(sidebar)/my-recruit/containers/AllRecruitment/AllRecruitment.tsx +++ b/src/app/(sidebar)/my-recruit/containers/AllRecruitment/AllRecruitment.tsx @@ -50,4 +50,4 @@ export function AllRecruitment() { ); -} +} \ No newline at end of file diff --git a/src/app/(sidebar)/my-recruit/containers/ProgressingRecruitment/ProgressingRecruitment.tsx b/src/app/(sidebar)/my-recruit/containers/ProgressingRecruitment/ProgressingRecruitment.tsx index 1d355703..2777fc11 100644 --- a/src/app/(sidebar)/my-recruit/containers/ProgressingRecruitment/ProgressingRecruitment.tsx +++ b/src/app/(sidebar)/my-recruit/containers/ProgressingRecruitment/ProgressingRecruitment.tsx @@ -29,4 +29,4 @@ export function ProgressingRecruitment() { ); -} +} \ No newline at end of file diff --git a/src/app/(sidebar)/my-recruit/containers/components/DueDateDialog.tsx b/src/app/(sidebar)/my-recruit/containers/components/DueDateDialog.tsx index a9efa67c..2acd9143 100644 --- a/src/app/(sidebar)/my-recruit/containers/components/DueDateDialog.tsx +++ b/src/app/(sidebar)/my-recruit/containers/components/DueDateDialog.tsx @@ -1,18 +1,18 @@ -import { Spacing } from '@/system/utils/Spacing'; +import { recruitStatusList } from '@/app/(sidebar)/my-recruit/constant'; import { Button, Dropdown, Icon } from '@/system/components'; +import { Calendar } from '@/system/components/Calendar/Calendar'; +import { Popover, PopoverContent, PopoverTrigger } from '@/system/components/Popover/Popover'; import { color } from '@/system/token/color'; +import { Spacing } from '@/system/utils/Spacing'; +import { cn } from '@/utils'; 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 { motion } from 'framer-motion'; import { useState } from 'react'; import { recruitScheduleStageList } from '../../constant'; -import { recruitStatusList } from '@/app/(sidebar)/my-recruit/constant'; -import { RecruitCard } from '../../type'; interface DueDateDialogProps { - title: string; + title?: string; onDuedateAppend: () => void; } @@ -33,13 +33,21 @@ export function DueDateDialog({ title }: DueDateDialogProps) { return (
- - - {title} - 의 공고 일정 등록하기 + {title && ( + <> + + + + )} + + {title ? `${title}의 공고 일정 등록하기` : '공고 일정 등록하기'} +
- 일정을 등록하면 잊지 않도록 알려드릴게요! + + 일정을 등록하면 잊지 않도록 알려드릴게요! + {/* 마감일 입력 */}
@@ -47,7 +55,7 @@ export function DueDateDialog({ title }: DueDateDialogProps) {
{currentRecruitStage} - + {title && }
diff --git a/src/app/(sidebar)/my-recruit/page.tsx b/src/app/(sidebar)/my-recruit/page.tsx index dcf79106..cbd6189b 100644 --- a/src/app/(sidebar)/my-recruit/page.tsx +++ b/src/app/(sidebar)/my-recruit/page.tsx @@ -113,4 +113,4 @@ export default function MyRecruit() { ); -} +} \ No newline at end of file diff --git a/src/app/(sidebar)/write/[id]/components/TagSelector/TagSelector.tsx b/src/app/(sidebar)/write/[id]/components/TagSelector/TagSelector.tsx index 4f42e43d..63c9a6ce 100644 --- a/src/app/(sidebar)/write/[id]/components/TagSelector/TagSelector.tsx +++ b/src/app/(sidebar)/write/[id]/components/TagSelector/TagSelector.tsx @@ -1,11 +1,11 @@ +import { generateContext } from '@/lib'; import { Button, ButtonProps } from '@/system/components'; +import { Remove } from '@/system/components/Icon/SVG/Remove'; +import { If } from '@/system/utils/If'; import type { StrictPropsWithChildren } from '@/types'; -import { UseTagSelectorProps, UseTagSelectorReturn, useTagSelector } from './useTagSelector'; -import { generateContext } from '@/lib'; import { cn } from '@/utils'; -import { Remove } from '@/system/components/Icon/SVG/Remove'; import { SVGProps } from 'react'; -import { If } from '@/system/utils/If'; +import { UseTagSelectorProps, UseTagSelectorReturn, useTagSelector } from './useTagSelector'; const [TagSelectorProvider, useTagSelectorContext] = generateContext< Omit @@ -60,11 +60,15 @@ function Trigger({ children, className }: StrictPropsWithChildren<{ className?: ); } -function Content({ children, className }: StrictPropsWithChildren<{ className?: string }>) { +function Content({ + children, + defaultOpen = false, + className, +}: StrictPropsWithChildren<{ defaultOpen?: boolean; className?: string }>) { const { isOpen, getContentProps } = useTagSelectorContext(); return ( - +
{children}
diff --git a/src/components/InfoCard.tsx b/src/components/InfoCard.tsx index d98224e6..32ac9156 100644 --- a/src/components/InfoCard.tsx +++ b/src/components/InfoCard.tsx @@ -64,4 +64,4 @@ export function InfoCard({ id, title, updatedDate, tagList }: InfoCardProps) {
); -} +} \ No newline at end of file diff --git a/src/container/Sidebar/Sidebar.tsx b/src/container/Sidebar/Sidebar.tsx index fb6963b7..32ab3500 100644 --- a/src/container/Sidebar/Sidebar.tsx +++ b/src/container/Sidebar/Sidebar.tsx @@ -1,13 +1,13 @@ 'use client'; +import { Logo } from '@/components/Logo'; import { SidebarButton } from '@/container/Sidebar/SidebarButton'; +import { MY_INFO_PATH, MY_RECRUIT_PATH } from '@/route'; import { Icon } from '@/system/components'; +import { cn } from '@/utils'; +import { usePathname, useRouter } from 'next/navigation'; import { useState } from 'react'; import { Collapsible } from './Collapsible/Collapsible'; -import { useRouter, usePathname } from 'next/navigation'; -import { MY_RECRUIT_PATH, MY_INFO_PATH } from '@/route'; -import { Logo } from '@/components/Logo'; -import { cn } from '@/utils'; const SIDEBAR_CLASSNAME = { expanded: 'w-[220px]', diff --git a/src/system/components/Icon/Icon.tsx b/src/system/components/Icon/Icon.tsx index 1ceb847b..c9ba26ba 100644 --- a/src/system/components/Icon/Icon.tsx +++ b/src/system/components/Icon/Icon.tsx @@ -1,41 +1,46 @@ -import { Search } from './SVG/Search'; -import { Folder } from './SVG/Folder'; -import { Bell } from './SVG/Bell'; -import { Memo } from './SVG/Memo'; -import { Profile } from './SVG/Profile'; -import { Setting } from './SVG/Setting'; -import { Logout } from './SVG/Logout'; -import { Down } from './SVG/Down'; -import { Add } from './SVG/Add'; -import { More } from './SVG/More'; -import { Division } from './SVG/Division'; -import { RightChevron } from './SVG/RightChevron'; -import { ProfileFill } from './SVG/ProfileFill'; +import { RemoveMemo } from '@/system/components/Icon/SVG/RemoveMemo'; +import { SubmitArrow } from '@/system/components/Icon/SVG/SubmitArrow'; import type { IconBaseType } from '@/system/components/Icon/SVG/type'; -import { Delete } from './SVG/Delete'; -import { Pip } from './SVG/Pip'; -import { X } from './SVG/X'; -import { Remove } from './SVG/Remove'; -import Copy from './SVG/Copy'; -import { Up } from './SVG/Up'; -import { Check } from './SVG/Check'; -import { Trash } from './SVG/Trash'; -import { Link } from './SVG/Link'; -import { Unlink } from './SVG/Unlink'; +import { Add } from './SVG/Add'; +import { Bell } from './SVG/Bell'; import { Calendar } from './SVG/Calendar'; import { CalendarFill } from './SVG/CalendarFill'; -import { SubmitArrow } from '@/system/components/Icon/SVG/SubmitArrow'; -import { FilledMemo } from './SVG/FilledMemo'; -import { RemoveMemo } from '@/system/components/Icon/SVG/RemoveMemo'; -import { Clover } from './SVG/Clover'; -import { DownChevron } from './SVG/DownChevron'; -import { FolderFill } from './SVG/FolderFill'; +import { Check } from './SVG/Check'; import { Close } from './SVG/Close'; -import { Kakao } from './SVG/KaKao'; import { CloverLogo } from '@/system/components/Icon/SVG/CloverLogo'; import { Google } from './SVG/Google'; import { CodingSignUp } from './SVG/CondingSignUp'; -import { DesignSignup } from './SVG/DesignSignUp'; +import { DesignSignup } from './SVG/DesignSignup'; +import { Clover } from './SVG/Clover'; +import { Copy } from './SVG/Copy'; +import { Delete } from './SVG/Delete'; +import { Division } from './SVG/Division'; +import { Down } from './SVG/Down'; +import { DownChevron } from './SVG/DownChevron'; +import { Empty } from './SVG/Empty'; +import { FilledMemo } from './SVG/FilledMemo'; +import { Folder } from './SVG/Folder'; +import { FolderFill } from './SVG/FolderFill'; +import { Link } from './SVG/Link'; +import { LogoOnly } from './SVG/LogoOnly'; +import { Logout } from './SVG/Logout'; +import { Memo } from './SVG/Memo'; +import { More } from './SVG/More'; +import { Pip } from './SVG/Pip'; +import { Profile } from './SVG/Profile'; +import { ProfileFill } from './SVG/ProfileFill'; +import { Refresh } from './SVG/Refresh'; +import { Remove } from './SVG/Remove'; +import { RightChevron } from './SVG/RightChevron'; +import { Rocket } from './SVG/Rocket'; +import { Search } from './SVG/Search'; +import { Setting } from './SVG/Setting'; +import { Shoes } from './SVG/Shoes'; +import { Tag } from './SVG/Tag'; +import { Trash } from './SVG/Trash'; +import { Unlink } from './SVG/Unlink'; +import { Up } from './SVG/Up'; +import { X } from './SVG/X'; const iconMap = { bell: Bell, @@ -74,6 +79,12 @@ const iconMap = { cloverLogo: CloverLogo, codingSignUp: CodingSignUp, designSignUp: DesignSignup, + refresh: Refresh, + empty: Empty, + tag: Tag, + shoes: Shoes, + rocket: Rocket, + logoOnly: LogoOnly, } as const; export interface IconProps extends IconBaseType { diff --git a/src/system/components/Icon/SVG/CodingSignUp.tsx b/src/system/components/Icon/SVG/CodingSignUp.tsx new file mode 100644 index 00000000..7254f06d --- /dev/null +++ b/src/system/components/Icon/SVG/CodingSignUp.tsx @@ -0,0 +1,43 @@ +import { IconBaseType } from './type'; + +export function CodingSignUp({ size }: IconBaseType) { + return ( + + + + + + + + + + + + + + + + + + ); +} diff --git a/src/system/components/Icon/SVG/Copy.tsx b/src/system/components/Icon/SVG/Copy.tsx index f154959d..f4b59ece 100644 --- a/src/system/components/Icon/SVG/Copy.tsx +++ b/src/system/components/Icon/SVG/Copy.tsx @@ -1,6 +1,6 @@ import { IconBaseType } from '@/system/components/Icon/SVG/type'; -export default function Copy({ size, color }: IconBaseType) { +export function Copy({ size, color }: IconBaseType) { return ( + + + + + + + + + + + + + + + + + + ); +} diff --git a/src/system/components/Icon/SVG/Empty.tsx b/src/system/components/Icon/SVG/Empty.tsx new file mode 100644 index 00000000..56d66d1c --- /dev/null +++ b/src/system/components/Icon/SVG/Empty.tsx @@ -0,0 +1,39 @@ +import { IconBaseType } from './type'; + +export function Empty({ size }: IconBaseType) { + return ( + + + + + + + + + + + + + + + ); +} diff --git a/src/system/components/Icon/SVG/LogoOnly.tsx b/src/system/components/Icon/SVG/LogoOnly.tsx new file mode 100644 index 00000000..f0aa043b --- /dev/null +++ b/src/system/components/Icon/SVG/LogoOnly.tsx @@ -0,0 +1,39 @@ +import { IconBaseType } from './type'; + +export function LogoOnly({ size, color }: IconBaseType) { + return ( + + + + + + + + + ); +} diff --git a/src/system/components/Icon/SVG/MemoColored.tsx b/src/system/components/Icon/SVG/MemoColored.tsx new file mode 100644 index 00000000..eb3fe4d3 --- /dev/null +++ b/src/system/components/Icon/SVG/MemoColored.tsx @@ -0,0 +1,14 @@ +import { IconBaseType } from './type'; + +export function MemoColored({ size }: IconBaseType) { + return ( + + + + + + + + + ); +} diff --git a/src/system/components/Icon/SVG/Refresh.tsx b/src/system/components/Icon/SVG/Refresh.tsx new file mode 100644 index 00000000..3af84a13 --- /dev/null +++ b/src/system/components/Icon/SVG/Refresh.tsx @@ -0,0 +1,19 @@ +import { IconBaseType } from './type'; + +export function Refresh({ size, color }: IconBaseType) { + return ( + + + + + ); +} diff --git a/src/system/components/Icon/SVG/Rocket.tsx b/src/system/components/Icon/SVG/Rocket.tsx new file mode 100644 index 00000000..4cacb1f2 --- /dev/null +++ b/src/system/components/Icon/SVG/Rocket.tsx @@ -0,0 +1,17 @@ +import { IconBaseType } from './type'; + +export function Rocket({ size, color }: IconBaseType) { + return ( + + + + + + + + + ); +} diff --git a/src/system/components/Icon/SVG/Shoes.tsx b/src/system/components/Icon/SVG/Shoes.tsx new file mode 100644 index 00000000..1af2e592 --- /dev/null +++ b/src/system/components/Icon/SVG/Shoes.tsx @@ -0,0 +1,19 @@ +import { IconBaseType } from './type'; + +export function Shoes({ size, color }: IconBaseType) { + return ( + + + + + + + + ); +} diff --git a/src/system/components/Icon/SVG/Tag.tsx b/src/system/components/Icon/SVG/Tag.tsx new file mode 100644 index 00000000..e1bc3f1a --- /dev/null +++ b/src/system/components/Icon/SVG/Tag.tsx @@ -0,0 +1,43 @@ +import { IconBaseType } from './type'; + +export function Tag({ size }: IconBaseType) { + return ( + + + + + + + + + + + + + + + + + + + + + + ); +}