Skip to content

Commit

Permalink
[FE] 약속 입장 페이지 구현 및 바로 약속 등록하기 페이지에서 바로 드래그/클릭으로 약속 등록이 가능하게 구현 (#403)
Browse files Browse the repository at this point in the history
* feat: MeetingInvitePage 구현

* fix: postSchedule 반환값 오류 수정 및 onSuccess로 콜백 처리 변경

- postSchedule 함수에서 반환값이 없는데 `return data.data`를 잘못 사용해 발생했던 오류 수정
- onSettled`를 제거하고 `onSuccess`로 콜백 처리 변경

* feat: MeetingRegisterPage 구현

* feat: SchedulePicker 컴포넌트에 register와 edit 모드에 따른 처리 로직 추가

* feat: MeetingConfirmCalendar.Picker 컴포넌트에 register와 edit 모드에 따른 처리 로직 추가

* feat: 날짜/시간을 등록할 때 아무것도 선택하지 않으면 버튼이 비활성화 되게 설정

* refactor: edit 모드에서 버튼 텍스트를 변경 (등록하기 → 수정하기)

* rename: 파일명 수정 (meeting/mutation → meeting/mutations)

* fix: navigate 경로 에러 수정

* rename: meeting 관련 api 호출 파일들을 meetings 디렉터리 내로 이동

* feat: MeetingInvitePage 버튼 상호작용 로직 구현

* feat: getMeetingInvitationDetails 함수 정의 및 적용

* rename: useGetMyScheduleQuery 훅을 schedule 관련 파일로 이동 (meeting → schedule)

* rename: 디렉터리명 수정 (MeetingTimePickPage → MeetingViewerPage)

* refactor: 일정 등록 및 수정 로직을 usePostScheduleByMode hook으로 통합

* rename: meetingInvite → meetingEntrance

'약속 초대'라는 의미를 '약속 입장'으로 변경

* feat: MSW 핸들러에 약속 타입(DATETIME, DAYSONLY)에 따른 meetingEntranceDetails API 응답 분기 처리 추가

* refactor: GlobalLayout으로 Suspense 처리 로직 이동
  • Loading branch information
Yoonkyoungme authored Oct 15, 2024
1 parent f01a403 commit e324f46
Show file tree
Hide file tree
Showing 41 changed files with 579 additions and 197 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BASE_URL } from '@constants/api';

import { fetchClient } from './_common/fetchClient';
import { fetchClient } from '../_common/fetchClient';
import type { MeetingType } from './meetings';

export interface ConfirmDates {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { ResponseError } from '@utils/responseError';

import { BASE_URL } from '@constants/api';

import { fetchClient } from './_common/fetchClient';
import { fetchClient } from '../_common/fetchClient';

export type MeetingType = 'DAYSONLY' | 'DATETIME';

interface MeetingBaseResponse {
meetingName: string;
firstTime: string;
Expand Down Expand Up @@ -136,3 +137,17 @@ export const unlockMeeting = async (uuid: string) => {
throw new ResponseError(data);
}
};

interface MeetingEntranceDetails {
meetingName: string;
type: MeetingType;
}

export const getMeetingEntranceDetails = async (uuid: string) => {
const data = await fetchClient<MeetingEntranceDetails>({
path: `/${uuid}/home`,
method: 'GET',
});

return data;
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fetchClient } from './_common/fetchClient';
import { fetchClient } from '../_common/fetchClient';
import type { MeetingType } from './meetings';

interface GetMeetingRecommendRequest {
Expand Down
31 changes: 20 additions & 11 deletions frontend/src/apis/schedules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,34 @@ import type {
MeetingSingleSchedule,
} from 'types/schedule';

import { ResponseError } from '@utils/responseError';

import { BASE_URL } from '@constants/api';

import { fetchClient } from './_common/fetchClient';

export const postSchedule = async ({
uuid,
requestData,
}: {
export interface PostScheduleRequest {
uuid: string;
requestData: MeetingSingeScheduleItem[];
}) => {
const path = `/${uuid}/schedules`;
}

await fetchClient({
path,
export const postSchedule = async ({ uuid, requestData }: PostScheduleRequest) => {
const response = await fetch(`${BASE_URL}/${uuid}/schedules`, {
method: 'POST',
body: {
dateTimes: requestData,
headers: {
'Content-Type': 'application/json',
},
isAuthRequire: true,
body: JSON.stringify({
dateTimes: requestData,
}),
credentials: 'include',
});

if (!response.ok) {
const data = await response.json();

throw new ResponseError(data);
}
};

export const createMeetingSchedulesRequestUrl = (uuid: string, attendeeName: string) => {
Expand Down
74 changes: 56 additions & 18 deletions frontend/src/components/MeetingConfirmCalendar/Picker/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useContext } from 'react';
import { useParams } from 'react-router-dom';
import { useNavigate, useParams } from 'react-router-dom';
import type { Mode } from 'types/schedule';

import { AuthContext } from '@contexts/AuthProvider';
import { TimePickerUpdateStateContext } from '@contexts/TimePickerUpdateStateProvider';
Expand All @@ -13,7 +14,7 @@ import Calendar from '@components/_common/Calendar';

import useCalendarPick from '@hooks/useCalendarPick/useCalendarPick';

import { usePostScheduleMutation } from '@stores/servers/schedule/mutations';
import { usePostScheduleByMode } from '@stores/servers/schedule/mutations';

import { getFullDate } from '@utils/date';

Expand All @@ -23,35 +24,48 @@ import WeekDays from '../WeekDays';

interface PickerProps {
availableDates: string[];
mode: Mode;
}

export default function Picker({ availableDates }: PickerProps) {
export default function Picker({ availableDates, mode }: PickerProps) {
const navigate = useNavigate();

const params = useParams<{ uuid: string }>();
const uuid = params.uuid!;
const { userName } = useContext(AuthContext).state;

const { userName } = useContext(AuthContext).state;
const { handleToggleIsTimePickerUpdate } = useContext(TimePickerUpdateStateContext);

const { selectedDates, hasDate, handleSelectedDate } = useCalendarPick(uuid, userName);

const { mutate: postScheduleMutate, isPending } = usePostScheduleMutation(() =>
handleToggleIsTimePickerUpdate(),
);
const { submitSchedule, isEditModePending, isRegisterModePending } = usePostScheduleByMode(mode);

// 백엔드에 날짜 데이터 보내주기 위해 임시로 generate함수 선언(@낙타)
const generateScheduleTable = (dates: string[]) => {
return dates.map((date) => {
const convertSelectedDatesToRequest = (dates: string[]) => {
const convertedData = dates.map((date) => {
return {
date,
times: ['00:00'],
};
});

return { uuid, requestData: convertedData };
};

const handleOnToggle = () => {
postScheduleMutate({ uuid, requestData: generateScheduleTable(selectedDates) });
const handleMeetingViewerNavigate = () => {
navigate(`/meeting/${uuid}/viewer`);
};

const handleScheduleSave = () => {
if (mode === 'register' && selectedDates.length === 0) {
return;
}

const scheduleRequestData = convertSelectedDatesToRequest(selectedDates);
submitSchedule(scheduleRequestData);
};

const isScheduleEmpty = selectedDates.length === 0;

return (
<>
<Calendar>
Expand All @@ -73,12 +87,36 @@ export default function Picker({ availableDates }: PickerProps) {

<footer css={s_bottomFixedButtonContainer}>
<div css={s_fullButtonContainer}>
<Button size="full" variant="secondary" onClick={handleToggleIsTimePickerUpdate}>
취소하기
</Button>
<Button size="full" variant="primary" onClick={handleOnToggle} isLoading={isPending}>
등록하기
</Button>
{mode === 'register' ? (
<>
<Button size="full" variant="secondary" onClick={handleMeetingViewerNavigate}>
약속 현황 조회
</Button>
<Button
size="full"
variant="primary"
onClick={handleScheduleSave}
isLoading={isRegisterModePending}
disabled={isScheduleEmpty}
>
등록하기
</Button>
</>
) : (
<>
<Button size="full" variant="secondary" onClick={handleToggleIsTimePickerUpdate}>
취소하기
</Button>
<Button
size="full"
variant="primary"
onClick={handleScheduleSave}
isLoading={isEditModePending}
>
수정하기
</Button>
</>
)}
</div>
</footer>
</>
Expand Down
12 changes: 10 additions & 2 deletions frontend/src/components/MeetingConfirmCalendar/Viewer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,19 @@ export default function Viewer({
<footer css={s_bottomFixedButtonContainer}>
<div css={s_fullButtonContainer}>
{hostName === userName ? (
<Button size="full" variant="primary" onClick={() => navigate('confirm')}>
<Button
size="full"
variant="primary"
onClick={() => navigate(`/meeting/${uuid}/confirm`)}
>
약속 시간 확정하기
</Button>
) : (
<Button size="full" variant="primary" onClick={() => navigate('recommend')}>
<Button
size="full"
variant="primary"
onClick={() => navigate(`/meeting/${uuid}/recommend`)}
>
약속 시간 추천받기
</Button>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import { useContext } from 'react';
import { useParams } from 'react-router-dom';
import type { MeetingDateTime } from 'types/meeting';
import type { Mode } from 'types/schedule';

import { AuthContext } from '@contexts/AuthProvider';

import { useGetMyScheduleQuery } from '@stores/servers/meeting/queries';
import { useGetMyScheduleQuery } from '@stores/servers/schedule/queries';

import SchedulePicker from '.';

interface SchedulePickerContainerProps extends MeetingDateTime {
mode: Mode;
}

export default function SchedulePickerContainer({
firstTime,
lastTime,
availableDates,
}: MeetingDateTime) {
mode,
}: SchedulePickerContainerProps) {
const params = useParams<{ uuid: string }>();
const uuid = params.uuid!;
const { userName } = useContext(AuthContext).state;
Expand All @@ -26,6 +32,7 @@ export default function SchedulePickerContainer({
lastTime={lastTime}
availableDates={availableDates}
meetingSingleSchedule={meetingSchedules}
mode={mode}
/>
)
);
Expand Down
Loading

0 comments on commit e324f46

Please sign in to comment.