Skip to content

Commit

Permalink
내 공고 내부 QA 반영 (#56)
Browse files Browse the repository at this point in the history
* api: set changed

* style: change recruit date

* feat: change data create

* api: data guard

* fix: fixing tag datas

* style: tagIcon moved

* style: visible dropdownArrow

* style: fixing style

* feat: changed query name

* feat : add copied style

* style: changed styled

* feat: styled

* feat: style

* style: changed padding

* style: linked color
  • Loading branch information
eunbeann authored Aug 30, 2024
1 parent 9a7fe3c commit 1b9823a
Show file tree
Hide file tree
Showing 18 changed files with 242 additions and 129 deletions.
6 changes: 5 additions & 1 deletion src/app/(sidebar)/(my-info)/apis/useDeleteCard.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { http } from '@/apis/http';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { GET_INFO_CARD_LIST } from './useGetInfoCardList';
import { GET_RECRUIT_CARD_COUNT } from '../../my-recruit/[id]/api/useGetCardCount';
import { GET_RECRUIT_CARD_ID } from '../../my-recruit/[id]/api/useGetRecruitCards';
import { GET_CARD_TYPE_COUNT } from './useGetCardTypeCount';
import { GET_INFO_CARD_LIST } from './useGetInfoCardList';

const deleteCard = (cardId: number) => {
return http.delete({
Expand All @@ -17,6 +19,8 @@ export const useDeleteCard = () => {
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [GET_INFO_CARD_LIST] });
queryClient.invalidateQueries({ queryKey: [GET_CARD_TYPE_COUNT] });
queryClient.invalidateQueries({ queryKey: [GET_RECRUIT_CARD_ID] });
queryClient.invalidateQueries({ queryKey: [GET_RECRUIT_CARD_COUNT] });
},
});
};
14 changes: 7 additions & 7 deletions src/app/(sidebar)/my-recruit/[id]/api/useGetCardCount.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { http } from '@/apis/http';
import { RecruitType } from '@/types/recruit';
import { useSuspenseQuery } from '@tanstack/react-query';
import { useQuery } from '@tanstack/react-query';

type GetCardCountType = Record<RecruitType, number>;

export const GET_CARD_COUNT = 'get-card-count';
export const GET_RECRUIT_CARD_COUNT = 'get-card-count';

const getCardCount = (id: string) => {
const getRecruitCardCount = (id: string) => {
return http.get<GetCardCountType>({
url: `/recruits/${id}/cards/type-count`,
});
};

export function useGetCardCount(id: string) {
const result = useSuspenseQuery({
queryKey: ['get-card-count'],
export function useGetRecruitCardCount(id: string) {
const result = useQuery({
queryKey: [GET_RECRUIT_CARD_COUNT],
queryFn: async () => {
const res = await getCardCount(id);
const res = await getRecruitCardCount(id);
return res.data;
},
});
Expand Down
11 changes: 5 additions & 6 deletions src/app/(sidebar)/my-recruit/[id]/api/useGetRecruitById.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@ const getRecruitById = (id: string) => {
});
};

export function useGetRecruitById(id: string) {
const result = useSuspenseQuery({
queryKey: [GET_RECRUIT_BY_ID, id],
export const useGetRecruitById = (id: string) => {
return useSuspenseQuery({
queryKey: [GET_RECRUIT_BY_ID],
queryFn: async () => {
const res = await getRecruitById(id);

return res.data;
},
});

return result;
}
};
4 changes: 2 additions & 2 deletions src/app/(sidebar)/my-recruit/[id]/api/useGetRecruitCards.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { http } from '@/apis/http';
import { TagType } from '@/types';
import { useSuspenseQuery } from '@tanstack/react-query';
import { useQuery } from '@tanstack/react-query';

export type GetRecruitCardsType = {
id: number;
Expand All @@ -22,7 +22,7 @@ const getRecruitCards = ({ id, type, tagIds }: { id: string; type: string; tagId
};

export function useGetRecruitCards({ id, type, tagIds }: { id: string; type: string; tagIds?: number[] }) {
const result = useSuspenseQuery({
const result = useQuery({
queryKey: [GET_RECRUIT_CARD_ID, id, type, tagIds],
queryFn: async () => {
const res = await getRecruitCards({ id, type, tagIds });
Expand Down
4 changes: 2 additions & 2 deletions src/app/(sidebar)/my-recruit/[id]/api/useGetSeason.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { http } from '@/apis/http';
import { useSuspenseQuery } from '@tanstack/react-query';
import { useQuery } from '@tanstack/react-query';

export interface SeasonType {
name: string;
Expand All @@ -14,7 +14,7 @@ const getSeasons = () => {
};

export function useGetSeasons() {
const result = useSuspenseQuery({
const result = useQuery({
queryKey: [GET_SEASONS],
queryFn: async () => {
const res = await getSeasons();
Expand Down
4 changes: 2 additions & 2 deletions src/app/(sidebar)/my-recruit/[id]/api/usePostCardInRecurit.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { http } from '@/apis/http';
import { RecruitType } from '@/types/recruit';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { GET_CARD_COUNT } from './useGetCardCount';
import { GET_RECRUIT_CARD_COUNT } from './useGetCardCount';
import { GET_RECRUIT_CARD_ID } from './useGetRecruitCards';

interface PostCardResponse {
Expand Down Expand Up @@ -39,7 +39,7 @@ export const usePostCardInRecruit = () => {
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [GET_RECRUIT_CARD_ID] });
queryClient.invalidateQueries({ queryKey: [GET_CARD_COUNT] });
queryClient.invalidateQueries({ queryKey: [GET_RECRUIT_CARD_COUNT] });
},
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Dialog, DialogClose, DialogContent, DialogTitle, DialogTrigger } from '
import { If } from '@/system/utils/If';
import { Spacing } from '@/system/utils/Spacing';
import { TagType } from '@/types/info';
import { RECRUIT_TYPES, RecruitType } from '@/types/recruit';
import { CHOOSE_RECRUIT_TYPES, RecruitType } from '@/types/recruit';
import { cn } from '@/utils/tailwind-util';
import { useRouter } from 'next/navigation';
import { PropsWithChildren, useState } from 'react';
Expand Down Expand Up @@ -151,7 +151,7 @@ export function AddRecruitCardDialog({ children, recruitId }: PropsWithChildren<
<TagSelector.Content className="w-full left-0 top-46 border-t-0 px-16 pt-16 pb-20">
<TagSelector.Notice className="pb-12">1개만 선택 가능해요!</TagSelector.Notice>
<TagSelector.TagList>
{RECRUIT_TYPES.map((type) => (
{CHOOSE_RECRUIT_TYPES.map((type) => (
<TagSelector.Tag
key={type}
className="text-yellow-1 bg-yellow-bg-1"
Expand Down
128 changes: 67 additions & 61 deletions src/app/(sidebar)/my-recruit/[id]/components/DetailContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import { cn } from '@/utils/tailwind-util';
import { useDndContext } from '@dnd-kit/core';
import { motion } from 'framer-motion';
import { useEffect, useRef, useState } from 'react';
import { useGetAllTags } from '../api/useGetAllTag';
import { useGetCardCount } from '../api/useGetCardCount';
import { useGetRecruitCardCount } from '../api/useGetCardCount';
import { useGetRecruitCards } from '../api/useGetRecruitCards';
import { AddRecruitCardDialog } from './AddRecruitCardDialog';
import TagList from './TagList';
Expand All @@ -22,10 +21,9 @@ export function DetailContent({ recruitId }: { recruitId: string }) {
const [scrollPosition, setScrollPosition] = useState(0);
const contentRef = useRef<HTMLDivElement>(null);

const { over } = useDndContext();
const { active } = useDndContext();

const { data: cardCount } = useGetCardCount(recruitId);
const { data: tagsData } = useGetAllTags();
const { data: cardCount } = useGetRecruitCardCount(recruitId);
const { data: cardList } = useGetRecruitCards({ id: recruitId, type: currentOption, tagIds: selectedTags });

const filteredCardList =
Expand Down Expand Up @@ -58,27 +56,40 @@ export function DetailContent({ recruitId }: { recruitId: string }) {
};

return (
<section className="flex-1 py-[64px] px-[80px]">
<section className="flex-1 py-[32px] px-[80px]">
<div className="flex justify-between mb-[28px]">
<div className="flex gap-[24px]">
<div className="flex items-center gap-24">
{RECRUIT_TYPES.map((option) => {
const isActive = currentOption === option;
const copyCardSelected = option === '내_정보_복사' && active;

return (
<TouchButton
key={option}
className="flex gap-[6px] items-center cursor-pointer"
onClick={() => setCurrentOption(option)}>
<div className={cn('text-[18px] font-semibold', isActive ? 'text-neutral-80' : 'text-neutral-10')}>
{option.replace(/_/g, ' ')}
</div>
<div
<Droppable key={option} id={1234}>
<TouchButton
className={cn(
'px-[8px] py-[2px] rounded-[6px] text-[14px] font-semibold',
isActive ? 'bg-neutral-80 text-neutral-1' : 'bg-neutral-10 text-neutral-1',
)}>
{cardCount?.[option]}
</div>
</TouchButton>
'flex gap-[6px] justify-center items-center cursor-pointer py-12 shrink-0',
copyCardSelected &&
'border-1 border-mint-30 bg-[rgba(221,243,235,0.50)] rounded-12 shrink-0 m-[-1px] px-12 -ml-13',
)}
onClick={() => setCurrentOption(option)}>
<div
className={cn(
'text-[18px] font-semibold ',
isActive ? 'text-neutral-80' : 'text-neutral-10',
copyCardSelected && 'text-mint-40',
)}>
{option.replace(/_/g, ' ')}
</div>
<div
className={cn(
'text-heading-2 px-[8px] py-[2px] rounded-[6px] text-[14px] font-semibold',
isActive ? 'bg-neutral-80 text-neutral-1' : 'bg-neutral-10 text-neutral-1',
copyCardSelected && 'bg-mint-30 text-neutral-1',
)}>
{cardCount?.[option] || 0}
</div>
</TouchButton>
</Droppable>
);
})}
</div>
Expand All @@ -96,47 +107,42 @@ export function DetailContent({ recruitId }: { recruitId: string }) {
</AddRecruitCardDialog>
</div>

<TagList tagsData={tagsData || []} selectedTags={selectedTags} setSelectedTags={setSelectedTags} />
<TagList selectedTags={selectedTags} setSelectedTags={setSelectedTags} />

<Droppable id={1234}>
<div
ref={contentRef}
className={cn(
'p-10 h-[calc(100vh-350px)] overflow-scroll [&::-webkit-scrollbar]:hidden',
over?.id === 1234 && 'file:border-mint-20 bg-[rgba(221,243,235,0.50)] rounded-20',
)}
style={{ scrollBehavior: 'smooth' }}>
{filteredCardList && filteredCardList.length > 0 ? (
<ul className="grid grid-cols-[repeat(auto-fill,minmax(343px,1fr))] gap-[16px]">
{filteredCardList.map((info: InfoCardType) => (
<li key={info.id} className="min-w-[343px]">
<InfoCard {...info} />
</li>
))}
{scrollPosition > 0 && (
<TouchButton
layout
onClick={scrollToTop}
className="fixed flex flex-col justify-center items-center a w-62 h-62 rounded-full right-[95px] bottom-[40px] bg-neutral-95 border-neutral-9">
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.5 }}>
<Icon name="arrowUp" size={24} />
<span className="text-neutral-1 text-caption1">TOP</span>
</motion.div>
</TouchButton>
)}
</ul>
) : (
<div className={'flex flex-col w-full h-full justify-center items-center'}>
<Icon name="empty" size={280} />
<p className="my-[16px] text-body1 text-neutral-30">아직 생성된 정보 카드가 없어요!</p>
</div>
)}
</div>
</Droppable>
<div
ref={contentRef}
className={'h-[calc(100vh-350px)] overflow-scroll [&::-webkit-scrollbar]:hidden'}
style={{ scrollBehavior: 'smooth' }}>
{filteredCardList && filteredCardList.length > 0 ? (
<ul className="grid grid-cols-[repeat(auto-fill,minmax(343px,1fr))] gap-[16px]">
{filteredCardList.map((info: InfoCardType) => (
<li key={info.id} className="min-w-[343px]">
<InfoCard {...info} />
</li>
))}
{scrollPosition > 0 && (
<TouchButton
layout
onClick={scrollToTop}
className="fixed flex flex-col justify-center items-center a w-62 h-62 rounded-full right-[95px] bottom-[40px] bg-neutral-95 border-neutral-9">
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.5 }}>
<Icon name="arrowUp" size={24} />
<span className="text-neutral-1 text-caption1">TOP</span>
</motion.div>
</TouchButton>
)}
</ul>
) : (
<div className={'flex flex-col w-full h-full justify-center items-center'}>
<Icon name="empty" size={280} />
<p className="my-[16px] text-body1 text-neutral-30">아직 생성된 정보 카드가 없어요!</p>
</div>
)}
</div>
</section>
);
}
15 changes: 5 additions & 10 deletions src/app/(sidebar)/my-recruit/[id]/components/DetailHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use client';

import { useOutsideClick } from '@/hooks/useOutsideClick';
import { Button, Icon } from '@/system/components';
import { color } from '@/system/token/color';
import { useRef, useState } from 'react';
Expand All @@ -12,16 +11,13 @@ import TitleInput from './TitleInput';

export default function DetailHeader({ recruitId }: { recruitId: string }) {
const { data: recruitInfoById } = useGetRecruitById(recruitId);
const siteUrl = recruitInfoById?.siteUrl;

const tooltipRef = useRef<HTMLDivElement>(null);
const [isFocused, setIsFocused] = useState(false);
const [isHovered, setIsHovered] = useState(false);
const [isLinked, setIsLinked] = useState(recruitInfoById.siteUrl !== '');

useOutsideClick(tooltipRef, () => setIsLinked(false));

const handleSetLink = () => {
setIsLinked(true);
setIsHovered(false);
};
let timeoutId: NodeJS.Timeout | null = null;
Expand All @@ -45,17 +41,16 @@ export default function DetailHeader({ recruitId }: { recruitId: string }) {
<SemesterSelector recruitId={recruitId} season={recruitInfoById?.season || ''} />
<ApplicationStatus recruitId={recruitId} status={recruitInfoById?.recruitStatus || ''} />

<TitleInput recruitInfoById={recruitInfoById} recruitId={recruitId} setIsFocused={setIsFocused} />
<TitleInput recruitId={recruitId} setIsFocused={setIsFocused} />

<div ref={tooltipRef} className="relative">
{!isFocused && (
<Button
className="flex justify-center items-center rounded-full hover:bg-neutral-1
hover:transition-delay: 2s hover:block"
aria-label={isLinked ? 'link button' : 'unlink button'}
className="flex justify-center items-center rounded-full hover:bg-neutral-1 hover:transition-delay: 2s hover:block"
aria-label={siteUrl ? 'link button' : 'unlink button'}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}>
<Icon name={isLinked ? 'link' : 'unlink'} size={16} color={isLinked ? color.mint40 : color.neutral40} />
<Icon name={siteUrl ? 'link' : 'unlink'} size={16} color={siteUrl ? color.mint40 : color.neutral40} />
</Button>
)}
<TextBubble isHovered={isHovered} linkedOn={handleSetLink} recruitId={recruitId} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ export default function SemesterSelector({ recruitId, season }: { recruitId: str

return (
<Dropdown>
<Dropdown.Trigger>
<div className="flex items-center border border-gray-200 bg-white rounded px-[8px] py-[4px] group">
<Dropdown.Trigger className="group">
<div className="flex h-28 items-center border border-gray-200 bg-white rounded px-[8px] py-[4px]">
<p className="text-label2 font-medium">{clickSemester}</p>
<span className="hidden group-hover:block group-active:block">
<Icon name="downChevron" size={22} color={color.neutral50} />
<span className="hidden group-hover:block group-active:block mt-[-2px]">
<Icon name="downChevron" size={20} color={color.neutral40} />
</span>
</div>
</Dropdown.Trigger>
Expand Down
Loading

0 comments on commit 1b9823a

Please sign in to comment.