Skip to content

Commit

Permalink
필터 기능 추가 (#26)
Browse files Browse the repository at this point in the history
* 필터 기능 추가

* 🐛 의존성 싱크 맞추기

* 🐛 충돌 해결

Co-authored-by: Yong <[email protected]>

* ⚡️ 타입 좁히기

* ✨ 카테고리 필터링 API 연결

* ✨ 언어별 필터링을 위해 쿼리함수 수정

* ✨ 언어별 필터링 API 연결

* ✨ 선택된 언어 동작 스타일 적용

---------

Co-authored-by: Sang-minKIM <[email protected]>
Co-authored-by: Yong <[email protected]>
  • Loading branch information
3 people authored Apr 8, 2024
1 parent c738796 commit 7d54c71
Show file tree
Hide file tree
Showing 13 changed files with 126 additions and 53 deletions.
1 change: 0 additions & 1 deletion src/entities/filter/index.ts

This file was deleted.

32 changes: 0 additions & 32 deletions src/entities/filter/ui/filter.ui.tsx

This file was deleted.

22 changes: 19 additions & 3 deletions src/entities/language/ui/language.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
import { useRecoilValue } from "recoil";
import styled from "styled-components";

import { languageState } from "~/widgets/language-rank/model/language-rank.atom";

interface LanguageProps {
language: string;
onLanguageClick: () => void;
id: number;
}

const Item = styled.div`
const Item = styled.button`
width: 100%;
height: 21px;
display: flex;
justify-content: center;
align-items: center;
gap: 16px;
background-color: transparent;
border: none;
color: ${({ theme }) => theme.colors.secondary};
&.active {
color: ${({ theme }) => theme.colors.white};
}
`;

export const Language = ({ language }: LanguageProps) => {
return <Item>{language}</Item>;
export const Language = ({ language, onLanguageClick, id }: LanguageProps) => {
const activeLanguageId = useRecoilValue(languageState);
return (
<Item onClick={onLanguageClick} className={activeLanguageId === id ? "active" : ""}>
{language}
</Item>
);
};
1 change: 1 addition & 0 deletions src/entities/question-list-filter/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./ui/question-list-filter.ui";
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { atom } from "recoil";

import { Category } from "./question-list-filter.type";

export const categoryState = atom<Category>({
key: "categoryState",
default: "popular",
});
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type Category = "popular" | "answered" | "not-answered" | "all";
58 changes: 58 additions & 0 deletions src/entities/question-list-filter/ui/question-list-filter.ui.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useRecoilState } from "recoil";
import styled from "styled-components";

import { categoryState } from "../model/question-list-filter.atom";
import { Category } from "../model/question-list-filter.type";

const filterArr = [
{
uiName: "Popular questions",
apiName: "popular",
},
{
uiName: "Answered",
apiName: "answered",
},
{
uiName: "All questions",
apiName: "all",
},
{
uiName: "Wait to be answered",
apiName: "not-answered",
},
];

const Ul = styled.ul`
display: flex;
justify-content: center;
gap: 50px;
`;

const Li = styled.li`
color: ${(props) => props.theme.colors.tabBar};
cursor: pointer;
&.active {
color: ${(props) => props.theme.colors.white};
}
`;

export const QuestionListFilter = () => {
const [category, setCategory] = useRecoilState(categoryState);

return (
<Ul>
{filterArr.map((item) => {
return (
<Li
key={item.uiName}
className={category === item.apiName ? "active" : ""}
onClick={() => setCategory(item.apiName as Category)}
>
{item.uiName}
</Li>
);
})}
</Ul>
);
};
10 changes: 5 additions & 5 deletions src/entities/question-list/api/question-list.key.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { ENV } from "~/shared/environment";

export const QUESTION_LIST_ENDPOINT = {
default: `${ENV.baseUrl}/api/question/page/popular`,
pagination: (body: { size: number; page: number }) =>
`${ENV.baseUrl}/api/question/page/popular?size=${body.size}&page=${body.page}`,
// default: `${ENV.baseUrl}/api/question/page/popular`,
pagination: (body: { category: string; size: number; page: number; language: number }) =>
`${ENV.baseUrl}/api/question/${body.category}?categories=${body.language || ""}&size=${body.size}&page=${body.page}`,
};

export const QUESTION_LIST_KEY = {
default: ["question-list"],
pagination: (body: { size: number; page: number }) => {
return [...QUESTION_LIST_KEY.default, body.size, body.page];
pagination: (body: { category: string; size: number; page: number; language: number }) => {
return [...QUESTION_LIST_KEY.default, body.category, body.size, body.page, body.language];
},
};
12 changes: 7 additions & 5 deletions src/entities/question-list/api/use-question-list.query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { UseQueryResult, useQuery } from "@tanstack/react-query";
import { QuestionListType } from "../model/question-list.type";
import { QUESTION_LIST_ENDPOINT, QUESTION_LIST_KEY } from "./question-list.key";

// Todo: 현재는 "popular"로 고정되어있지만, 추후에는 인자로 받아서 사용할 수 있도록 변경해야합니다.
// "전체","답변된 질문","답변되지 않은 질문" 등등..
export const useQuestionListQuery = (page: number): UseQueryResult<QuestionListType> => {
export const useQuestionListQuery = (
category: string,
page: number,
language: number
): UseQueryResult<QuestionListType> => {
const questionList = useQuery<QuestionListType>({
queryKey: QUESTION_LIST_KEY.pagination({ size: 10, page }),
queryKey: QUESTION_LIST_KEY.pagination({ category, size: 10, page, language }),
queryFn: async () => {
const response = await fetch(QUESTION_LIST_ENDPOINT.pagination({ size: 10, page }), { method: "POST" });
const response = await fetch(QUESTION_LIST_ENDPOINT.pagination({ category, size: 10, page, language }));
const json = await response.json();
return json;
},
Expand Down
6 changes: 6 additions & 0 deletions src/widgets/language-rank/model/language-rank.atom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { atom } from "recoil";

export const languageState = atom({
key: "languageState",
default: 0,
});
10 changes: 9 additions & 1 deletion src/widgets/language-rank/ui/language-rank.ui.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { useSetRecoilState } from "recoil";
import styled from "styled-components";

import { Language } from "~/entities/language/ui/language";
import { Sidebar } from "~/entities/sidebar";

import { useLanguageRankQuery } from "../api/use-language-rank.query";
import { languageState } from "../model/language-rank.atom";

const LanguageList = styled.div`
width: 100%;
Expand All @@ -16,7 +18,13 @@ const LanguageList = styled.div`

export const LanguageRank = () => {
const { data, isPending, isError } = useLanguageRankQuery();
const listElements = data?.slice(0, 10).map(({ id, name }) => <Language key={id} language={name} />);
const setLanguageState = useSetRecoilState(languageState);
const onLanguageClick = (id: number) => {
setLanguageState(id);
};
const listElements = data
?.slice(0, 10)
.map(({ id, name }) => <Language key={id} id={id} onLanguageClick={() => onLanguageClick(id)} language={name} />);

if (isPending) {
return <div>...loading</div>;
Expand Down
14 changes: 10 additions & 4 deletions src/widgets/question-list/ui/question-list.ui.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { useSearchParams } from "react-router-dom";
import { useRecoilValue } from "recoil";
import styled from "styled-components";

import { languageState } from "~/widgets/language-rank/model/language-rank.atom";

import { Question } from "~/entities/question";
import { categoryState } from "~/entities/question-list-filter/model/question-list-filter.atom";
import { useQuestionListQuery } from "~/entities/question-list/api/use-question-list.query";
import { useQuestionSearchQuery } from "~/entities/question-list/api/use-question-search.query";

Expand Down Expand Up @@ -30,11 +34,14 @@ const QuestionListContainer = styled.div`
export const QuestionList = () => {
const [searchParams] = useSearchParams();
const currentPage = Number(searchParams?.get("page")) || 1;
const category = useRecoilValue(categoryState);
const language = useRecoilValue(languageState);

const { data: questions, isPending, isError } = useQuestionListQuery(category, currentPage - 1, language);
const searchTerm = searchParams?.get("search") || "";
// Todo: 현재는 "popular"로 고정되어있지만, 인자로 받아서 사용할 수 있도록 변경해야합니다.
// "전체","답변된 질문","답변되지 않은 질문" 등등..

const { goToReumi } = useReumi();
const { data: questions, isPending, isError } = useQuestionListQuery(currentPage - 1);

const {
data: searchedQuestionData,
isPending: isSearchedPending,
Expand All @@ -48,7 +55,6 @@ export const QuestionList = () => {
if (isError || isSearchedError) {
return <div>Error</div>;
}

const data = searchTerm ? searchedQuestionData : questions.content;

return (
Expand Down
4 changes: 2 additions & 2 deletions src/widgets/top-filter/ui/top.ui.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import styled from "styled-components";

import { Filter } from "~/entities/filter";
import { QuestionButton } from "~/entities/question-button";
import { QuestionListFilter } from "~/entities/question-list-filter";

const Wrapper = styled.div`
width: 100%;
Expand All @@ -21,7 +21,7 @@ const Wrapper = styled.div`
export const Top = ({ isWritePage = false }: { isWritePage?: boolean }) => {
return (
<Wrapper>
<Filter />
<QuestionListFilter />
{!isWritePage && <QuestionButton />}
</Wrapper>
);
Expand Down

0 comments on commit 7d54c71

Please sign in to comment.