Skip to content

Commit

Permalink
feat(web-domains): about 페이지 손 흔들기 기능 추가 (#121)
Browse files Browse the repository at this point in the history
* feat: 타인 마이페이지에서 손흔들기 버튼 추가

* feat: 손흔들기 요청 처리

* fix: 버튼 상태 처리 수정

* fix: 버튼 상태 string 수정

* feat: 손 흔들기 상태 조회 처리
  • Loading branch information
Doeunnkimm authored Aug 22, 2024
1 parent 44611fc commit cb4e144
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';

import { Http } from '@/common/apis/base.api';

import { HAND_WAVINGS_STATUS_QUERY_KEY } from '../queries/useGetHandWavingsStatus';

interface Request {
meetingId: number;
receiverMemberId: number;
}

export const useCreateHandWavings = () => {
const queryClient = useQueryClient();

return useMutation({
mutationFn: ({ meetingId, receiverMemberId }: Request) =>
Http.POST(`/v1/meetings/${meetingId}/hand-wavings`, { receiverMemberId }),
onSuccess: (_, variable) => queryClient.invalidateQueries({ queryKey: [HAND_WAVINGS_STATUS_QUERY_KEY, variable] }),
});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { QueryClient, useQuery, UseQueryOptions } from '@tanstack/react-query';

import { Http } from '@/common/apis/base.api';

import { HandWavingStatusResponse } from '../schema/HandWavingStatusResponse';

interface Params {
meetingId: number;
receiverMemberId: number;
}

interface QueryProps extends Params {
options?: UseQueryOptions<HandWavingStatusResponse>;
}

const queryFn = ({ meetingId, receiverMemberId }: Params) =>
Http.GET<HandWavingStatusResponse>(`/v1/meetings/${meetingId}/hand-wavings/receiver/${receiverMemberId}/status`);

export const HAND_WAVINGS_STATUS_QUERY_KEY = 'HAND_WAVINGS_STATUS_QUERY_KEY ';

export const useGetHandWavingsStatus = (props: QueryProps) => {
const { options, ...params } = props;

return useQuery({
queryKey: [HAND_WAVINGS_STATUS_QUERY_KEY, params],
queryFn: () => queryFn(params),
enabled: params.meetingId > 0,
staleTime: 1000 * 60 * 10, // 10분
...options,
});
};

interface PrefetchProps extends Params {
queryClient: QueryClient;
}

export const getHandWavingsStatusPrefetch = (props: PrefetchProps) => {
const { queryClient, ...params } = props;

const prefetch = queryClient.prefetchQuery({
queryKey: [HAND_WAVINGS_STATUS_QUERY_KEY, params],
queryFn: () => queryFn(params),
});

return prefetch;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface HandWavingStatusResponse {
HandWavingId: number;
status: 'REQUESTED' | 'ACCEPTED' | 'REJECTED';
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,53 @@
'use client';

import { colors, size } from '@sambad/sds/theme';
import { Fragment } from 'react';
import { colors, shadow, size } from '@sambad/sds/theme';
import { Button } from '@sds/components';

import { useCreateHandWavings } from '@/about-me/common/apis/mutates/useCreateHandWavings';
import { useGetHandWavingsStatus } from '@/about-me/common/apis/queries/useGetHandWavingsStatus';
import { ActionBar } from '@/common/components/ActionBar/ActionBar';

import { useGetFirstMeetingId } from '../hooks/useGetFirstMeetingId';
import { useIsMyByParams } from '../hooks/useIsMyByParams';

import { ProfileContainer } from './ProfileContainer';
import { SegmentedControlContainer } from './SegmentedControlContainer';
import { handWavingButtonCss, screenRootCss } from './styles';

export const ScreenContainer = () => {
const { isMy, meetingMemberId } = useIsMyByParams();
const { meetingId } = useGetFirstMeetingId();
const { data: wavingStatusData, isSuccess: getWavingStatusSuccess } = useGetHandWavingsStatus({
meetingId,
receiverMemberId: meetingMemberId,
});
const { mutate, isSuccess: sendWavingSuccess } = useCreateHandWavings();

const isProgressHandWavings = sendWavingSuccess || wavingStatusData?.status === 'REQUESTED';

const handleHandWaving = () => {
mutate({ meetingId, receiverMemberId: meetingMemberId });
};

return (
<Fragment>
<ActionBar title="프로필" />
<div css={screenRootCss}>
<ActionBar title={isMy ? '마이 프로필' : '프로필'} />
<div style={layoutStyle}>
<ProfileContainer style={{ marginBottom: size['5xs'] }} />
<SegmentedControlContainer style={sectionStyle} />
</div>
</Fragment>
{!isMy && getWavingStatusSuccess && (
<Button
size="large"
disabled={isProgressHandWavings}
onClick={handleHandWaving}
css={handWavingButtonCss}
style={{ boxShadow: isProgressHandWavings ? shadow.elevation3 : undefined }}
>
{isProgressHandWavings ? '손 흔들어 인사하기 완료!' : '손 흔들어 인사하기'}
</Button>
)}
</div>
);
};

Expand Down
10 changes: 10 additions & 0 deletions packages/web-domains/src/about-me/features/containers/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,13 @@ export const answerContentCss = css({
marginTop: size['7xs'],
},
});

export const handWavingButtonCss = css({
position: 'absolute',
bottom: size['xl'],
});

export const screenRootCss = css({
position: 'relative',
height: '100dvh',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { useGetMeetings } from '@/about-me/common/apis/queries/useGetMeetings';

export const useGetFirstMeetingId = () => {
const { data } = useGetMeetings();
// NOTE: 하나의 모임에 참여할 수 있는 현재 스펙에서 첫 번째 meetingId를 가져옴
const meetingId = data?.meetings[0]?.meetingId || -1;

return { meetingId };
};

0 comments on commit cb4e144

Please sign in to comment.