Skip to content

Commit

Permalink
[#80] Feat: 내가 응원한 떡국 api 적용 (#105)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kim-Jaemin420 authored Feb 7, 2024
1 parent 339d96c commit 43d20e5
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 34 deletions.
10 changes: 9 additions & 1 deletion src/apis/myActivity.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { GetReceivedIngredientsResponse } from "@/types/myActivity.dto";
import {
GetMySupportedTteokguksRespose,
GetReceivedIngredientsResponse,
} from "@/types/myActivity.dto";

import http from "./core";

const RECEIVED_INGREDIENTS_SIZE = 10;

export const getMySupportedTteokguks = (page: number) =>
http.get<GetMySupportedTteokguksRespose>(
`api/v1/support?page=${page}&size=${RECEIVED_INGREDIENTS_SIZE}`,
);

export const getReceivedIngredients = (page: number) =>
http.get<GetReceivedIngredientsResponse>(
`api/v1/support/ingredient?page=${page}&size=${RECEIVED_INGREDIENTS_SIZE}`,
Expand Down
87 changes: 87 additions & 0 deletions src/components/MyActivity/MySupportedTteokgukCardList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { css } from "@styled-system/css";

import { MySupportedTteokguk } from "@/types/myActivity";

import TteokgukImage from "@/components/common/TteokgukImage";
import { Link } from "@/routes/Link";

interface Props {
tteokguks: MySupportedTteokguk[];
}

const MySupportedTteokgukCardList = ({ tteokguks }: Props) => {
return (
<ul className={styles.container}>
{tteokguks.map(
({
tteokgukId,
receiverNickname,
completion,
backgroundColor,
frontGarnish,
backGarnish,
}) => (
<li key={tteokgukId} className={styles.cardContainer}>
<Link to={`/tteokguks/${tteokgukId}`}>
<div>
<div className={styles.imageContainer}>
<TteokgukImage
completion={completion}
backgroundColor={backgroundColor}
frontGarnish={frontGarnish}
backGarnish={backGarnish}
/>
</div>
<div className={styles.cardContent}>
<div className={styles.cardTitle}>{tteokgukId}번째 소원떡국</div>
<div className={styles.cardNickname}>@ {receiverNickname}</div>
</div>
</div>
</Link>
</li>
),
)}
</ul>
);
};

export default MySupportedTteokgukCardList;

const styles = {
container: css({
display: "flex",
flexFlow: "row wrap",
gap: "1.6rem",
}),
cardContainer: css({
position: "relative",
maxWidth: "calc(50% - 1.6rem)",
width: "100%",
height: "20.5rem",
boxSizing: "border-box",
borderRadius: "1rem",
overflow: "hidden",
paddingBottom: "5.3rem",
}),
imageContainer: css({
position: "relative",
display: "flex",
justifyContent: "center",
height: "15.2rem",
backgroundColor: "white",
overflow: "hidden",
}),
cardContent: css({
width: "100%",
height: "5.3rem",
backgroundColor: "primary.80",
padding: "0.8rem 1rem 0",
}),
cardTitle: css({
fontSize: "1.4rem",
fontWeight: 700,
}),
cardNickname: css({
fontSize: "1.2rem",
}),
};
2 changes: 1 addition & 1 deletion src/components/TteokgukCookingPage/Ingredient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const Ingredient = ({
isDisabled,
handleClickIngredient,
}: Props) => {
const isInfiniteQuantity = stockQuantity === MAX_INGREDIENT_QUANTITY;
const isInfiniteQuantity = stockQuantity >= MAX_INGREDIENT_QUANTITY;
const remainQuantity = isSelected ? stockQuantity - 1 : stockQuantity;
const quantity = isInfiniteQuantity ? INFINITY : remainQuantity;

Expand Down
2 changes: 1 addition & 1 deletion src/components/common/BottomCTA.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const styles = {
bottom: 0,
left: 0,
width: "100%",
padding: "1rem 0 4rem 0",
padding: "1rem 0 9.1rem 0",
transform: isVisible ? "translateY(0%)" : "translateY(100%)",
transition: "transform 0.4s",
zIndex: 100,
Expand Down
2 changes: 1 addition & 1 deletion src/components/common/ReceivedIngredientsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const ReceivedIngredientsList = ({ receivedIngredientList }: Props) => {
</div>
<div>
<div className={styles.title}>@{access ? nickname : ANONIMOUS_NICKNAME}</div>
<div>응원의 {INGREDIENT_NAME_BY_KEY[ingredient]} 도착했어요!</div>
<div>응원의 {INGREDIENT_NAME_BY_KEY[ingredient]}(이/가) 도착했어요!</div>
</div>
</div>
<div className={styles.buttonContainer}>
Expand Down
1 change: 0 additions & 1 deletion src/pages/MainPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ const styles = {
position: "fixed",
left: "50%",
transform: "translateX(-50%)",
bottom: "3rem",
width: "calc(100% - 4.8rem)",
maxWidth: "45.2rem",
}),
Expand Down
55 changes: 39 additions & 16 deletions src/pages/MyActivityPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,40 @@ import { css } from "@styled-system/css";

import Header from "@/components/common/Header";
import ReceivedIngredientsList from "@/components/common/ReceivedIngredientsList";
import TteokgukWithCaptionList from "@/components/common/TteokgukWithCaptionList";
import { $receivedIngredients } from "@/store/myActivity";
import { $mySupportedTteokguks, $receivedIngredients } from "@/store/myActivity";
import Loading from "@/components/common/Loading";
import MySupportedTteokgukCardList from "@/components/MyActivity/MySupportedTteokgukCardList";

const MyActivityPage = () => {
const [tabIndex, setTabIndex] = useState(0);
const isSelectedTab = (index: number) => index === tabIndex;

const {
mySupportedTteokguks,
isPending: isMySupportedTteokguksPending,
handleSupportedTtoekguksIntersect,
} = useAtomValue($mySupportedTteokguks);
const fetchMoreRef = useRef(null);

const { receivedIngredientList, handleReceivedIngredeintIntersect } =
useAtomValue($receivedIngredients);
const {
receivedIngredientList,
handleReceivedIngredeintIntersect,
isPending: isReceivedTteokgukPending,
} = useAtomValue($receivedIngredients);

useIntersectionObserver({
target: fetchMoreRef,
handleIntersect: () => handleReceivedIngredeintIntersect({ enabled: isSelectedTab(0) }),
handleIntersect:
tabIndex === 0
? () => handleReceivedIngredeintIntersect({ enabled: isSelectedTab(0) })
: () => handleSupportedTtoekguksIntersect({ enabled: isSelectedTab(1) }),
});
console.log(mySupportedTteokguks);

return (
<Fragment>
<Header showBackButton>활동 내역</Header>
<div className={styles.container}>
{(isReceivedTteokgukPending || isMySupportedTteokguksPending) && <Loading />}
<Tabs selectedIndex={tabIndex} onSelect={(index) => setTabIndex(index)}>
<TabList className={styles.tabList}>
<Tab className={classNames({ [styles.selectedTab]: isSelectedTab(0) })}>
Expand All @@ -40,11 +53,15 @@ const MyActivityPage = () => {
내가 응원한 떡국
</Tab>
</TabList>
<TabPanel className={styles.tabPanel}>
<ReceivedIngredientsList receivedIngredientList={receivedIngredientList} />
<TabPanel className={styles.receivedTab}>
{receivedIngredientList && (
<ReceivedIngredientsList receivedIngredientList={receivedIngredientList} />
)}
</TabPanel>
<TabPanel className={styles.tabPanel}>
<TteokgukWithCaptionList tteokguks={[]} />
<TabPanel className={styles.mySupportedTab}>
{mySupportedTteokguks && (
<MySupportedTteokgukCardList tteokguks={mySupportedTteokguks} />
)}
</TabPanel>
</Tabs>
<div ref={fetchMoreRef} />
Expand All @@ -70,12 +87,6 @@ const styles = {
marginBottom: "2rem",
cursor: "pointer",
}),
tabPanel: css({
display: "flex",
flexFlow: "column wrap",
paddingX: "1.8rem",
width: "100%",
}),
selectedTab: css({
position: "relative",
outline: "none",
Expand All @@ -90,6 +101,18 @@ const styles = {
backgroundColor: "primary.100",
},
}),
receivedTab: css({
display: "flex",
flexFlow: "column wrap",
paddingX: "1.8rem",
width: "100%",
}),
mySupportedTab: css({
display: "flex",
flexFlow: "column wrap",
alignItems: "center",
paddingLeft: "1.6rem",
}),
tteokgukList: css({
display: "flex",
flexFlow: "row wrap",
Expand Down
2 changes: 1 addition & 1 deletion src/pages/TteokgukPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ const styles = {
height: "17.6rem",
}),
content: css({
height: "7.1rem",
minHeight: "7.1rem",
fontSize: "1.4rem",
backgroundColor: "primary.100",
padding: "1rem 1.6rem",
Expand Down
50 changes: 39 additions & 11 deletions src/store/myActivity.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { atomWithSuspenseInfiniteQuery } from "jotai-tanstack-query";
import { atomWithInfiniteQuery } from "jotai-tanstack-query";
import { atom } from "jotai";

import { getReceivedIngredients } from "@/apis/myActivity";
import { getReceivedIngredients, getMySupportedTteokguks } from "@/apis/myActivity";

const $getReceivedIngredients = atomWithSuspenseInfiniteQuery(() => ({
const $getReceivedIngredients = atomWithInfiniteQuery(() => ({
queryKey: ["receivedIngredients"],
queryFn: async ({ pageParam }) => getReceivedIngredients(pageParam),
getNextPageParam: (lastPage, _allPages, lastPageParam) => {
Expand All @@ -15,13 +15,9 @@ const $getReceivedIngredients = atomWithSuspenseInfiniteQuery(() => ({
}));

export const $receivedIngredients = atom(async (get) => {
const {
data: { pages },
fetchNextPage,
hasNextPage,
isFetchingNextPage,
...rest
} = await get($getReceivedIngredients);
const { data, fetchNextPage, hasNextPage, isFetchingNextPage, ...rest } = await get(
$getReceivedIngredients,
);

const handleReceivedIngredeintIntersect = ({ enabled }: { enabled: boolean }) => {
if (hasNextPage && !isFetchingNextPage && enabled) {
Expand All @@ -30,11 +26,43 @@ export const $receivedIngredients = atom(async (get) => {
};

return {
receivedIngredientList: pages.flatMap(({ data: receivedIngredients }) => receivedIngredients),
receivedIngredientList: data?.pages.flatMap(
({ data: receivedIngredients }) => receivedIngredients,
),
fetchNextPage,
hasNextPage,
isFetchingNextPage,
handleReceivedIngredeintIntersect,
...rest,
};
});

const $getMySupportedTteokguks = atomWithInfiniteQuery(() => ({
queryKey: ["supportedTteokguks"],
queryFn: async ({ pageParam }) => getMySupportedTteokguks(pageParam),
getNextPageParam: (lastPage, _allPages, lastPageParam) => {
if (!lastPage.data.length) return;

return lastPageParam + 1;
},
initialPageParam: 1,
}));

export const $mySupportedTteokguks = atom((get) => {
const { data, hasNextPage, isFetchingNextPage, fetchNextPage, ...rest } =
get($getMySupportedTteokguks);

const handleSupportedTtoekguksIntersect = ({ enabled }: { enabled: boolean }) => {
if (hasNextPage && !isFetchingNextPage && enabled) {
fetchNextPage();
}
};

return {
mySupportedTteokguks: data?.pages.flatMap(
({ data: mySupportedTteokguks }) => mySupportedTteokguks,
),
handleSupportedTtoekguksIntersect,
...rest,
};
});
10 changes: 9 additions & 1 deletion src/types/myActivity.dto.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ReceivedIngredient } from "./myActivity";
import { MySupportedTteokguk, ReceivedIngredient } from "./myActivity";

export interface GetReceivedIngredientsResponse {
data: ReceivedIngredient[];
Expand All @@ -7,3 +7,11 @@ export interface GetReceivedIngredientsResponse {
size: number;
};
}

export interface GetMySupportedTteokguksRespose {
data: MySupportedTteokguk[];
pageInfo: {
page: number;
size: number;
};
}
10 changes: 10 additions & 0 deletions src/types/myActivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,13 @@ export interface ReceivedIngredient {
message: string;
access: boolean;
}

export interface MySupportedTteokguk {
tteokgukId: number;
receiverNickname: string;
ingredients: IngredientKey[];
completion: boolean;
frontGarnish: IngredientKey;
backGarnish: IngredientKey;
backgroundColor: "BLUE" | "GREEN" | "PINK" | "YELLOW";
}

0 comments on commit 43d20e5

Please sign in to comment.