Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

해주세요 목록 페이지 구현 #251

Merged
merged 7 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions frontend/src/apis/endPoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ const ENDPOINTS = {
auth: getEndpoint('v1/auth'),
chamyo: getEndpoint('v1/chamyo'),
zzim: getEndpoint('v1/zzim'),
interest: getEndpoint('v1/interest'),
please: getEndpoint('v1/please'),
};
export default ENDPOINTS;
9 changes: 8 additions & 1 deletion frontend/src/apis/gets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
GetChat,
GetMoim,
GetMoims,
GetPleases,
GetMyInfo,
GetZzimMine,
} from './responseTypes';
Expand Down Expand Up @@ -87,9 +88,15 @@ export const getChamyoAll = async (
return json.data.chamyos;
};

export const getPleases = async () => {
const response = await ApiClient.getWithAuth('please');

const json: GetPleases = await response.json();
return json.data.pleases;
};

export const getMyInfo = async () => {
const response = await ApiClient.getWithAuth('member/mine');
checkStatus(response);

const json: GetMyInfo = await response.json();
return json.data;
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/apis/posts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,10 @@ export const postChat = async (moimId: number, content: string) => {
content,
});
};

export const postInterest = async (pleaseId: number, interesting: boolean) => {
await ApiClient.postWithAuth('interest', {
pleaseId,
interesting,
});
};
8 changes: 7 additions & 1 deletion frontend/src/apis/responseTypes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Chat, MoimInfo, Participation } from '../types';
import { Chat, MoimInfo, Participation, Please } from '../types';

export interface GetMoims {
data: { moims: MoimInfo[] };
Expand Down Expand Up @@ -34,6 +34,12 @@ export interface GetZzimMine {
};
}

export interface GetPleases {
data: {
pleases: Please[];
};
}

export interface GetMyInfo {
data: {
nickname: string;
Expand Down
28 changes: 28 additions & 0 deletions frontend/src/components/Icons/InterestingIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useTheme } from '@emotion/react';

interface InterestingIconProps {
isActive: boolean;
}

export default function InterestingIcon(props: InterestingIconProps) {
const { isActive } = props;

const theme = useTheme();

return (
<svg
width="24"
height="24"
viewBox="0 0 19 21"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M8.2 2C8.2 0.895 8.896 0 10 0C11.104 0 11.8 0.895 11.8 2L12 10C12 9.636 12.5 4.34 12.5 4C12.5 3 13.095 2 14.2 2C15.305 2 16 2.895 16 4V11.268C16.083 11.22 16.3 7.422 16.3 7C16.3 6 16.563 5 17.5 5C18.438 5 19 5.895 19 7V13C19 15.1217 18.1571 17.1566 16.6569 18.6569C15.1566 20.1571 13.1217 21 11 21H10.326C8.84041 21 7.38417 20.5862 6.12045 19.8052C4.85672 19.0242 3.83543 17.9067 3.171 16.578L0.329001 10.894C-0.0349991 10.166 0.245001 9.226 1.049 8.87C1.472 8.683 1.946 8.578 2.392 8.72C3.5 9.073 3.336 9.58 4 10.21V4C4 2.895 4.695 2 5.8 2C6.8 2 7.409 3.315 7.5 4C7.625 4.938 8 9.634 8 9.998L8.2 2Z"
fill={isActive ? theme.semantic.primary : theme.semantic.disabled}
/>
</svg>
);
}
1 change: 0 additions & 1 deletion frontend/src/components/MoimCard/MoimCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export default function MoimCard(props: MoimCardProps) {

const handleHeartButtonClick = (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
console.log(1);
changeZzim(moimId);
};

Expand Down
36 changes: 36 additions & 0 deletions frontend/src/components/PleaseCard/PleaseCard.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { Meta, StoryObj } from '@storybook/react';
import PleaseCard from './PleaseCard';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient();

const meta = {
component: PleaseCard,
title: 'Components/PleaseCard',
decorators: [
(Story) => {
return (
<QueryClientProvider client={queryClient}>
<Story />
</QueryClientProvider>
);
},
],
} satisfies Meta<typeof PleaseCard>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
please: {
pleaseId: 1,
title: '제목',
description: '설명',
interestCount: 0,
isInterested: false,
},
},
render: (args) => <PleaseCard {...args} />,
};
75 changes: 75 additions & 0 deletions frontend/src/components/PleaseCard/PleaseCard.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { css, Theme } from '@emotion/react';

export const cardBox = css`
display: flex;
gap: 1.6rem;
justify-content: space-between;

width: 100%;
padding: 2rem 2.4rem;

border-radius: 2.5rem;
box-shadow: rgb(0 0 0 / 24%) 0 3px 8px;
`;

export const contentWrapper = css`
display: flex;
flex-direction: column;
gap: 0.8rem;
`;

export const headerWrapper = css`
display: flex;
gap: 0.6rem;
align-items: center;
`;

export const title = ({ theme }: { theme: Theme }) => css`
${theme.typography.s1}
`;

export const count = ({ theme }: { theme: Theme }) => css`
${theme.typography.c3}
`;

export const countAccent = ({ theme }: { theme: Theme }) => css`
${theme.typography.c3}
color: ${theme.semantic.primary};
`;

export const description = ({ theme }: { theme: Theme }) => css`
${theme.typography.c3}
`;

export const actionWrapper = css`
display: flex;
`;

export const actionButton = css`
display: flex;
flex-direction: column;
gap: 14px;
align-items: center;
justify-content: center;

padding: 0;

background: none;
border: none;
`;

export const actionIconWrapper = ({ theme }: { theme: Theme }) => css`
display: flex;

padding: 8px;

background-color: ${theme.colorPalette.grey[100]};
border: none;
border-radius: 16px;
box-shadow: rgb(0 0 0 / 24%) 0 3px 8px;
`;

export const actionText = ({ theme }: { theme: Theme }) => css`
${theme.typography.c3}
white-space: nowrap;
`;
44 changes: 44 additions & 0 deletions frontend/src/components/PleaseCard/PleaseCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Please } from '@_types/index';
import * as S from './PleaseCard.style';
import { useTheme } from '@emotion/react';
import InterestingIcon from '@_components/Icons/InterestingIcon';
import useInterest from '@_hooks/mutaions/useInterest';

interface PleaseCardProps {
please: Please;
}

export default function PleaseCard(props: PleaseCardProps) {
const { please, ...args } = props;

const theme = useTheme();

const { mutate: changeInterest } = useInterest(please);

const handleInterestButtonClick = () => {
changeInterest();
};

return (
<div css={S.cardBox} {...args}>
<div css={S.contentWrapper}>
<div css={S.headerWrapper}>
<div css={S.title({ theme })}>{please.title}</div>
<div css={S.count({ theme })}>
<span css={S.countAccent({ theme })}>{please.interestCount}명</span>
이 관심 보이는 중👀
</div>
</div>
<div css={S.description({ theme })}>{please.description}</div>
</div>
<div css={S.actionWrapper}>
<button css={S.actionButton} onClick={handleInterestButtonClick}>
<div css={S.actionIconWrapper({ theme })}>
<InterestingIcon isActive={please.isInterested} />
</div>
<div css={S.actionText({ theme })}>관심있어요</div>
</button>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { css } from '@emotion/react';

export const cardListSection = css`
display: flex;
flex-direction: column;
gap: 1.2rem;
`;
19 changes: 19 additions & 0 deletions frontend/src/components/PleaseCardList/PleaseCardList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import PleaseCard from '@_components/PleaseCard/PleaseCard';
import { Please } from '@_types/index';
import * as S from './PleaseCardList.style';

interface PleaseCardListProps {
pleases: Please[];
}

export default function PleaseCardList(props: PleaseCardListProps) {
const { pleases } = props;

return (
<div css={S.cardListSection}>
{pleases.map((please) => (
<PleaseCard key={please.pleaseId} please={please} />
))}
</div>
);
}
12 changes: 12 additions & 0 deletions frontend/src/components/PleaseList/PleaseList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import PleaseCardList from '@_components/PleaseCardList/PleaseCardList';
import usePleases from '@_hooks/queries/usePleases';

export default function PleaseList() {
const { pleases, isLoading } = usePleases();

if (isLoading) {
return <div>로딩중...</div>;
}

return pleases && <PleaseCardList pleases={pleases} />;
}
1 change: 1 addition & 0 deletions frontend/src/constants/queryKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const QUERY_KEYS = {
ZzimMine: 'ZzimMine',
chamyoAll: 'chamyoAll',
comment: 'comment',
pleases: 'pleases',
myInfo: 'MyInfo',
};

Expand Down
17 changes: 17 additions & 0 deletions frontend/src/hooks/mutaions/useInterest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { postInterest } from '@_apis/posts';
import QUERY_KEYS from '@_constants/queryKeys';
import { Please } from '@_types/index';
import { useMutation, useQueryClient } from '@tanstack/react-query';

export default function useInterest(please: Please) {
const queryClient = useQueryClient();

return useMutation({
mutationFn: () => postInterest(please.pleaseId, !please.isInterested),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: [QUERY_KEYS.pleases],
});
},
});
}
12 changes: 12 additions & 0 deletions frontend/src/hooks/queries/usePleases.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { getPleases } from '@_apis/gets';
import QUERY_KEYS from '@_constants/queryKeys';
import { useQuery } from '@tanstack/react-query';

export default function usePleases() {
const { data: pleases, isLoading } = useQuery({
queryKey: [QUERY_KEYS.pleases],
queryFn: () => getPleases(),
});

return { pleases, isLoading };
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { DISPLAY_MAX_WIDTH } from '@_constants/styles';
import { css, Theme } from '@emotion/react';

export const headerStyle = css`
position: fixed;
top: 0;

width: 100%;
max-width: ${DISPLAY_MAX_WIDTH};
padding: 14px 22px;

background-color: white;
`;

export const logoStyle = (props: { theme: Theme }) => css`
Expand Down
6 changes: 1 addition & 5 deletions frontend/src/layouts/HomeLayout.tsx/HomeLayout.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ import { NAVIGATION_BAR_HEIGHT } from '@_constants/styles';
import { css } from '@emotion/react';

export const containerStyle = css`
display: flex;
flex-direction: column;
gap: 1rem;

margin-top: 8.6rem;
margin-bottom: ${NAVIGATION_BAR_HEIGHT};
padding-bottom: 2rem;
`;
2 changes: 0 additions & 2 deletions frontend/src/layouts/HomeLayout.tsx/HomeLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import HomeFixedButtonWrapper from './HomeFixedButtonWrapper/HomeFixedButtonWrap
import HomeHeader from './HomeHeader/HomeHeader';
import HomeMain from './HomeMain/HomeMain';
import { PropsWithChildren } from 'react';
import HomeNav from './HomeNav/HomeNav';

function HomeLayout(props: PropsWithChildren) {
const { children } = props;
Expand All @@ -13,7 +12,6 @@ function HomeLayout(props: PropsWithChildren) {
}

HomeLayout.Header = HomeHeader;
HomeLayout.Nav = HomeNav;
HomeLayout.Main = HomeMain;
HomeLayout.HomeFixedButtonWrapper = HomeFixedButtonWrapper;

Expand Down
10 changes: 4 additions & 6 deletions frontend/src/layouts/HomeLayout.tsx/HomeMain/HomeMain.style.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { css } from '@emotion/react';
import { css, Theme } from '@emotion/react';

export const mainStyle = css`
display: flex;
flex-direction: column;
gap: 38px;
padding: 0 22px;
export const mainStyle = ({ theme }: { theme: Theme }) => css`
padding: 16px 22px;
background-color: ${theme.colorPalette.grey[100]};
`;
Loading
Loading