Skip to content

Commit

Permalink
Merge branch 'develop' into feat/#101
Browse files Browse the repository at this point in the history
  • Loading branch information
hyo-4 committed May 22, 2024
2 parents d73508d + 045463b commit 10bd086
Show file tree
Hide file tree
Showing 14 changed files with 406 additions and 93 deletions.
38 changes: 38 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"@mui/material": "^5.15.17",
"@mui/x-date-pickers": "^7.4.0",
"@react-oauth/google": "^0.12.1",
"@tanstack/react-query": "^5.37.1",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
Expand Down
34 changes: 20 additions & 14 deletions src/components/Experience/KeywordTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ import ExpData from "../../services/JD/ExpData";
import editIcon from "../../assets/images/editIcon.png";
import { useNavigate } from "react-router-dom";
import {
deleteTag,
getPrimeTagSubTags,
getPrimeTagYears,
} from "../../services/Experience/tagApi";
import { getCookie } from "../../services/cookie";
Expand All @@ -47,6 +45,7 @@ import {
} from "../../types/experience";
import { getExperienceList } from "../../services/Experience/experienceApi";
import { getKeywords } from "../../services/Experience/keywordApi";
import { useSubTagsQuery } from "../hooks/useSubTagsQuery";

type TabType = "basic" | "my";
interface KeywordTabProp {
Expand All @@ -59,9 +58,16 @@ const KeywordTab = ({ openDeleteModal }: KeywordTabProp) => {
const navigate = useNavigate();
const [selectedYear, setSelectedYear] = useRecoilState(yearState);
const [isDelete, setIsDelete] = useRecoilState(deleteState);
const [selectedDeleteTag, setSelectedDeleteTag] = useRecoilState(deleteTagState);
const [selectedDeleteTag, setSelectedDeleteTag] =
useRecoilState(deleteTagState);
const [selectedPrimeTag, setSelectedPrimeTag] = useRecoilState(primeTagState);
const [selectedSubTag, setSelectedSubTag] = useRecoilState(subTagState);

const { data: subTagsData, isSuccess: isSubTagsSuccess } = useSubTagsQuery(
selectedYear,
selectedPrimeTag?.id,
user?.token
);
const [selectedQ, setSelectedQ] = React.useState(0);
const [expanded, setExpanded] = React.useState(false); // 질문 아코디언 관리
const [keywordTabOption, setKeywordTabOption] =
Expand Down Expand Up @@ -188,21 +194,21 @@ const KeywordTab = ({ openDeleteModal }: KeywordTabProp) => {

// 상위태그 내 하위태그 목록 조회 (메뉴)
React.useEffect(() => {
if (selectedYear && selectedPrimeTag && user?.token) {
getPrimeTagSubTags(selectedYear, selectedPrimeTag.id, user?.token).then(
(res) => {
const { totalExperienceCount, tagInfos } = res.data;
setTotalExpCount(totalExperienceCount);
setSubTagMenus(tagInfos);
setSelectedSubTag(null);
}
);
if (isSubTagsSuccess && subTagsData) {
const { totalExperienceCount, tagInfos } = subTagsData;
setTotalExpCount(totalExperienceCount);
setSubTagMenus(tagInfos);
setSelectedSubTag(null);
// 하위 태그 목록이 없을 경우 사이드 탭 닫히는 로직
if (tagInfos.length === 0) {
setSelectedPrimeTag(null);
}
}
}, [selectedYear, selectedPrimeTag, user?.token]);
}, [isSubTagsSuccess, subTagsData]);

// 상위태그 연도 리스트 조회
React.useEffect(() => {
if (selectedPrimeTag && user?.token) {
if (selectedPrimeTag && selectedPrimeTag.id !== "더보기" && user?.token) {
getPrimeTagYears(selectedPrimeTag.id, user?.token).then((res) =>
setPrimeTagYears(res.data.years)
);
Expand Down
34 changes: 22 additions & 12 deletions src/components/Experience/YearList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import {
primeTagState,
yearState,
} from "../../store/selectedStore";
import { getExperienceYears } from "../../services/Experience/experienceApi";
import { getCookie } from "../../services/cookie";
import { TagType, YearData } from "../../types/experience";
import { useExperienceYearsQuery } from "../hooks/useExperienceYearsQuery";

interface YearListProps {
width: number;
Expand All @@ -25,9 +25,21 @@ const YearList = ({ width, openDeleteModal }: YearListProps) => {
const setSelectedPrimeTag = useSetRecoilState<TagType | null>(primeTagState);
const [isDelete, setIsDelete] = useRecoilState(deleteState);
const [years, setYears] = React.useState<number[]>([]);
const [allYearsData, setAllYearsData] = React.useState<YearData[]>([]);

const [allTagsData, setAllTagsData] = React.useState<YearData[]>([]);
const [hoveredYear, setHoveredYear] = useState<number | null>(null);
const { data: allYearsData, isSuccess: isAllYearsDataSucces } =
useExperienceYearsQuery(user?.token);

// 상위태그 목록이 없을 경우 year 원 닫히는 로직
if (allYearsData) {
const { yearTagInfos } = allYearsData;
const selectedYearPrimeTags = yearTagInfos?.filter(
(item) => item.year === selectedYear
)?.[0]?.tags;
if (selectedYearPrimeTags?.length === 0) {
setSelectedYear(null);
}
}

// 클릭한 year 객체로 스크롤 이동하기 위한 객체 참조 값
const yearRefs = useRef<{ [key: number]: HTMLDivElement | null }>({});
Expand Down Expand Up @@ -95,15 +107,13 @@ const YearList = ({ width, openDeleteModal }: YearListProps) => {
};

// 전체 연도 및 연도별 태그 목록 정보
useEffect(() => {
if (user?.token) {
getExperienceYears(user?.token).then((res) => {
const { years, yearTagInfos } = res.data;
setYears(years);
setAllYearsData(yearTagInfos);
});
React.useEffect(() => {
if (isAllYearsDataSucces && allYearsData) {
const { years, yearTagInfos } = allYearsData;
setYears(years);
setAllTagsData(yearTagInfos);
}
}, [user?.token]);
}, [isAllYearsDataSucces, allYearsData]);

// 클릭한 연도 원형 중심으로 스크롤 이동
useEffect(() => {
Expand All @@ -119,7 +129,7 @@ const YearList = ({ width, openDeleteModal }: YearListProps) => {
//
return (
<Line length={lineLength}>
{allYearsData?.map((data, index) => (
{allTagsData?.map((data, index) => (
<YearMotionDiv
ref={(el) => (yearRefs.current[data.year] = el)}
key={data.year}
Expand Down
3 changes: 3 additions & 0 deletions src/components/common/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import styled from "styled-components";
import logo from "../../assets/images/logo.png";
import { useLocation, useNavigate } from "react-router-dom";
import { getCookie } from "../../services/cookie";
import { useGetUserInfo } from "../hooks/useGetUserInfo";

const Navbar = () => {
const navigate = useNavigate();
const location = useLocation();
const user = getCookie("user");
const { data: userData } = useGetUserInfo(user?.token);

const handleImgError = (e: React.SyntheticEvent<HTMLImageElement, Event>) => {
e.currentTarget.src = `${process.env.PUBLIC_URL}/assets/profile1.png`;
Expand Down Expand Up @@ -39,6 +41,7 @@ const Navbar = () => {
<>
<img
src={
userData?.profileImgUrl ||
user?.profileImgUrl ||
`${process.env.PUBLIC_URL}/assets/profile1.png`
}
Expand Down
33 changes: 33 additions & 0 deletions src/components/hooks/useExperienceYearsQuery.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useQuery } from "@tanstack/react-query";
import { TagType } from "../../types/experience";
import { AxiosError, AxiosResponse } from "axios";
import { getExperienceYears } from "../../services/Experience/experienceApi";

interface ExperienceYearsResType {
years: number[];
yearTagInfos: { year: number; tags: TagType[] }[];
}

export const useExperienceYearsQuery = (token: string) => {
const queryKey = ["experienceYears", token];

const queryFn = async (): Promise<ExperienceYearsResType> => {
if (token) {
const response: AxiosResponse<ExperienceYearsResType> =
await getExperienceYears(token);
return response.data;
}
throw new Error("Missing parameters");
};

const { isLoading, isError, data, error, isSuccess, refetch } = useQuery<
ExperienceYearsResType,
AxiosError
>({
queryKey,
queryFn,
enabled: !!token,
});

return { isLoading, isError, data, error, isSuccess, refetch };
};
27 changes: 27 additions & 0 deletions src/components/hooks/useGetUserInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useQuery } from "@tanstack/react-query";
import { AxiosError, AxiosResponse } from "axios";
import { UserDataType } from "../../types/user";
import { getUserInfo } from "../../services/user";

export const useGetUserInfo = (token: string) => {
const queryKey = ["userInfo", token];

const queryFn = async (): Promise<UserDataType> => {
if (token) {
const response: AxiosResponse<UserDataType> = await getUserInfo(token);
return response.data;
}
throw new Error("Missing parameters");
};

const { isLoading, isError, data, error, isSuccess, refetch } = useQuery<
UserDataType,
AxiosError
>({
queryKey,
queryFn,
enabled: !!token,
});

return { isLoading, isError, data, error, isSuccess, refetch };
};
37 changes: 37 additions & 0 deletions src/components/hooks/useSubTagsQuery.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useQuery } from "@tanstack/react-query";
import { getPrimeTagSubTags } from "../../services/Experience/tagApi";
import { TagMenuType } from "../../types/experience";
import { AxiosError, AxiosResponse } from "axios";

interface PrimeTagSubTagsResType {
totalExperienceCount: number;
tagInfos: TagMenuType[];
}

export const useSubTagsQuery = (
year: number | null,
primeTagId: string | undefined,
token: string
) => {
const queryKey = ["primeTagSubTags", year, primeTagId, token];

const queryFn = async (): Promise<PrimeTagSubTagsResType> => {
if (year && primeTagId && token) {
const response: AxiosResponse<PrimeTagSubTagsResType> =
await getPrimeTagSubTags(year, primeTagId, token);
return response.data;
}
throw new Error("Missing parameters");
};

const { isLoading, isError, data, error, isSuccess, refetch } = useQuery<
PrimeTagSubTagsResType,
AxiosError
>({
queryKey,
queryFn,
enabled: !!(year && primeTagId && token),
});

return { isLoading, isError, data, error, isSuccess, refetch };
};
18 changes: 11 additions & 7 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,24 @@ import { BrowserRouter } from "react-router-dom";
import { GoogleOAuthProvider } from "@react-oauth/google";
import { ThemeProvider } from "styled-components";
import { theme } from "./styles/theme";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

const queryClient = new QueryClient();
const GOOGLE_CLIENT_ID = process.env.REACT_APP_GOOGLE_CLIENT_ID;
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<BrowserRouter>
<ThemeProvider theme={theme}>
<RecoilRoot>
<GoogleOAuthProvider clientId={`${GOOGLE_CLIENT_ID}`}>
<App />
</GoogleOAuthProvider>
</RecoilRoot>
</ThemeProvider>
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={theme}>
<RecoilRoot>
<GoogleOAuthProvider clientId={`${GOOGLE_CLIENT_ID}`}>
<App />
</GoogleOAuthProvider>
</RecoilRoot>
</ThemeProvider>
</QueryClientProvider>
</BrowserRouter>
);

Expand Down
Loading

0 comments on commit 10bd086

Please sign in to comment.