Skip to content

Commit

Permalink
Merge pull request #14 from Read-bird/feature/yj
Browse files Browse the repository at this point in the history
기능수정 및 api 연결
  • Loading branch information
devwoodie authored Dec 19, 2023
2 parents 5f2efab + b99c1f9 commit 8884726
Show file tree
Hide file tree
Showing 15 changed files with 257 additions and 151 deletions.
22 changes: 19 additions & 3 deletions src/api/axios.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
import axios from 'axios';

export const authFetch = axios.create({
baseURL: `${process.env.REACT_APP_SERVER_PATH}`
baseURL: `${process.env.REACT_APP_SERVER_PATH}`,
headers: {
'Content-Type': 'application/json',
Accept: 'application/json'
}
});

authFetch.interceptors.request.use(
(config) => {
config.headers['Content-Type'] = 'application/json';
config.headers['Accept'] = 'application/json';
config.headers.Authorization = `${localStorage.getItem('rb-access-token')}`;
config.headers.refreshtoken = `${localStorage.getItem('rb-refresh-token')}`;
return config;
},
(error) => {
return Promise.reject(error);
}
);

authFetch.interceptors.response.use(
(response) => response,
async (error) => {
const status = error.response.status;
if (status === 412) {
const result = await authFetch.post('/api/user/token');
localStorage.setItem('rb-access-token', result.headers?.authorization);
}

return Promise.reject(error);
}
);
34 changes: 34 additions & 0 deletions src/api/plan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { authFetch } from '@api/axios';
import { TPlanData } from '@api/types';
import { AxiosError } from 'axios';

type TResponse<T> = { error: boolean; success: boolean; data: T };

// 플랜 조회하기
export const getPlanList = async (date: string): Promise<TResponse<TPlanData | string>> => {
try {
const result = await authFetch.get('/api/plan', { params: { date } });
return { error: false, success: true, data: result.data };
} catch (e) {
if (e instanceof AxiosError) {
return { error: true, success: false, data: e.response?.data.message ?? '' };
}

return { error: true, success: false, data: '' };
}
};

// 플랜 삭제하기
export const deletePlan = async (planId: number, userId: number): Promise<TResponse<string>> => {
try {
const result = await authFetch.delete(`/api/plan/${planId}`, { data: { userId } });

return { error: false, success: true, data: result.data };
} catch (e: any) {
if (e instanceof AxiosError) {
return { error: true, success: false, data: e.response?.data.message ?? '' };
}

return { error: true, success: false, data: '' };
}
};
10 changes: 5 additions & 5 deletions src/api/types/planRecord.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ export enum ERecordStatus {

// 주간 플랜달성데이터
export type TPlanRecord = {
createdAt: string;
status: EAchievementStatus | null;
date: string;
achievementStatus: EAchievementStatus | null;
};

// 플랜조회 데이터
Expand All @@ -35,7 +35,7 @@ export type TPreviouslyFailedPlan = Omit<TPlan, 'target' | 'planStatus' | 'recor

// 전체 타입
export type TPlanData = {
weedRecord: TPlanRecord[] | null;
planData: TPlan[] | null;
previouslyFailedPlan: TPreviouslyFailedPlan[] | null;
weedRecord: TPlanRecord[];
planData: TPlan[];
previouslyFailedPlan: TPreviouslyFailedPlan[];
};
2 changes: 1 addition & 1 deletion src/assets/images/Images.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type TProps = {
imgStyle?: CSSObject;
};

export const Images = memo(({ imgUrl, imgAlt, imgWidth, imgHeight, imgStyle }: TProps) => {
export const Images = memo(({ imgUrl = '', imgAlt, imgWidth, imgHeight, imgStyle }: TProps) => {
const handleError = useCallback((e: SyntheticEvent<HTMLImageElement, Event>) => {
e.currentTarget.src = require('/src/assets/images/noImage.jpeg');
}, []);
Expand Down
8 changes: 4 additions & 4 deletions src/components/common/Calendar/Calendar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TPlanRecord } from '@api/types';
import { DayBird } from '@components/common/DayBird';
import { cls, getClassByStatus } from '@utils/classname';
import { convertMap } from '@utils/function';
import { convertObject } from '@utils/function';
import dayjs from 'dayjs';
import { useCallback, useMemo } from 'react';
import ReactCalendar, { TileContentFunc, TileDisabledFunc } from 'react-calendar';
Expand All @@ -14,7 +14,7 @@ type TProps = {
};

export const Calendar = ({ record, currentDate, changeCurrentDate }: TProps) => {
const planDateRecord = useMemo(() => convertMap(record, 'createdAt'), [record]);
const planDateRecord = useMemo(() => convertObject(record, 'date'), [record]);
const onChange = (value: Date) => {
changeCurrentDate(dayjs(value).format());
};
Expand All @@ -23,8 +23,8 @@ export const Calendar = ({ record, currentDate, changeCurrentDate }: TProps) =>
({ date }) => {
const formatDate = dayjs(date).format('YYYY-MM-DD');

const data = planDateRecord.get(formatDate);
const className = getClassByStatus(date, data?.status ?? null, currentDate);
const data = planDateRecord[formatDate];
const className = getClassByStatus(date, data?.achievementStatus ?? null, currentDate);

return (
<DayBird
Expand Down
20 changes: 12 additions & 8 deletions src/components/common/Calendar/WeekCalendar.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { TPlanRecord } from '@api/types';
import { DayBird } from '@components/common/DayBird';
import { DAY_OF_WEEK } from '@constants/plan';
import { makeWeekArr } from '@utils/calendar';
import { cls, getClassByStatus } from '@utils/classname';
import dayjs from 'dayjs';
import { useMemo } from 'react';
import styled from 'styled-components';

type TProps = {
record: TPlanRecord[];
currentDate: string;
record: Record<string, TPlanRecord>;
currentDate: Date;
};

export const WeekCalendar = ({ record, currentDate }: TProps) => {
const weeks = useMemo(() => makeWeekArr(currentDate), [currentDate]);

return (
<Wrap>
<FlexBox>
Expand All @@ -21,14 +25,14 @@ export const WeekCalendar = ({ record, currentDate }: TProps) => {
))}
</FlexBox>
<FlexBox>
{record.map((weekRecord) => {
const date = new Date(weekRecord.createdAt);
const nowDate = new Date(currentDate);
const className = getClassByStatus(date, weekRecord.status, nowDate);
{weeks.map((date) => {
const achievementStatus =
record[dayjs(date).format('YYYY-MM-DD')]?.achievementStatus ?? null;
const className = getClassByStatus(date, achievementStatus, currentDate);

return (
<DayBird key={`${weekRecord.createdAt}`} className={cls(className)}>
<Text className={cls(className)}>{dayjs(weekRecord.createdAt).format('DD')}</Text>
<DayBird key={`${date}`} className={cls(className)}>
<Text className={cls(className)}>{dayjs(date).format('DD')}</Text>
</DayBird>
);
})}
Expand Down
27 changes: 25 additions & 2 deletions src/components/templates/HomeTemplate/HomeTemplate.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { setCurrentDate } from '@/store/reducers';
import { setCurrentDate, setPlan } from '@/store/reducers';
import { TAppDispatch, TRootState } from '@/store/state';
import { getPlanList } from '@api/plan';
import { IconReact } from '@assets/icons';
import { CalendarBird } from '@components/common/CalendarBird';
import { Spacing } from '@components/common/Spacing';
import { colors } from '@style/global-style';
import { Alert } from '@utils/Alert';
import { lastDayMonth } from '@utils/calendar';
import dayjs from 'dayjs';
import { useMemo } from 'react';
import { useEffect, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Outlet, useLocation, useNavigate } from 'react-router-dom';
import { Body, CalendarWrap, FlexBox, Head, TodayText, Wrap } from './Styled';
Expand Down Expand Up @@ -35,6 +37,27 @@ export const HomeTemplate = () => {
dispatch(setCurrentDate(dayjs(currentDate).add(1, 'month').format()));
};

const getList = async () => {
const result = await getPlanList(dayjs(currentDate).format('YYYY-MM-DD'));

if (typeof result.data !== 'string') {
dispatch(setPlan({ ...result.data }));
} else if (result.error) {
if (result.data) {
Alert.error({
title: result.data,
action: () => {
dispatch(setPlan({ weedRecord: [], planData: [], previouslyFailedPlan: [] }));
}
});
}
}
};

useEffect(() => {
getList();
}, []);

return (
<Wrap>
<Head>
Expand Down
38 changes: 26 additions & 12 deletions src/components/templates/HomeTemplate/Plan/Dots/Dots.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { TRootState } from '@/store/state';
import { deletePlan } from '@api/plan';
import { IconReact } from '@assets/icons';
import { MiniModal } from '@components/templates/HomeTemplate/Plan/Modal';
import { colors } from '@style/global-style';
import { Alert } from '@utils/Alert';
import { MouseEvent, useCallback, useState } from 'react';
import { useSelector } from 'react-redux';
import styled from 'styled-components';

type TProps = {
Expand All @@ -11,6 +14,7 @@ type TProps = {

export const Dots = ({ planId }: TProps) => {
const [isOpen, setOpen] = useState<number | null>(null);
const { userId } = useSelector((state: TRootState) => state.userStore);

const handleClose = useCallback(() => {
setOpen(null);
Expand All @@ -29,18 +33,28 @@ export const Dots = ({ planId }: TProps) => {
setOpen(null);
}, []);

const handleClickRemove = useCallback(() => {
Alert.confirm({
title: '이 플랜을 정말 삭제할까요?',
text: '* 삭제된 플랜은 마이페이지에서 2주동안 보관됩니다.',
action: (result) => {
if (result.isConfirmed) {
Alert.success({ title: '삭제되었습니다!' });
const handleClickRemove = useCallback(
(planId: number, userId: number | null) => () => {
if (userId === null) return;

Alert.confirm({
title: '이 플랜을 정말 삭제할까요?',
text: '* 삭제된 플랜은 마이페이지에서 2주동안 보관됩니다.',
action: async (result) => {
if (result.isConfirmed) {
const result = await deletePlan(planId, userId);
if (result.success) {
Alert.success({ title: '삭제되었습니다!' });
} else {
Alert.error({ title: `${result.data.replace('Bad Request :', '')}` });
}
setOpen(null);
}
}
setOpen(null);
}
});
}, []);
});
},
[]
);

return (
<Wrap>
Expand All @@ -53,7 +67,7 @@ export const Dots = ({ planId }: TProps) => {
/>
<MiniModal isOpen={isOpen === planId} handleClick={handleClose}>
<Button onClick={handleClickOpenEdit}>수정</Button>
<Button onClick={handleClickRemove}>삭제</Button>
<Button onClick={handleClickRemove(planId, userId)}>삭제</Button>
</MiniModal>
</Wrap>
);
Expand Down
Loading

0 comments on commit 8884726

Please sign in to comment.