Skip to content

Commit

Permalink
[FE] Feature/#317 권한 관련 기능 구현 (#318)
Browse files Browse the repository at this point in the history
* refactor :불필요한 페이지 삭제

* refactor: 헤더에 토큰 추가 방식 변경

* feat: 기능 요구사항 구현

* feat: 추가 기능 구현
  • Loading branch information
jiwonh423 authored Aug 16, 2023
1 parent 980748e commit f892740
Show file tree
Hide file tree
Showing 15 changed files with 376 additions and 58 deletions.
21 changes: 17 additions & 4 deletions frontend/src/apis/getApi.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
interface Headers {
'Content-Type': string;
[key: string]: string;
}

export const getApi = async <T>(
type: 'tMap' | 'default' | 'login',
url: string,
Expand All @@ -7,16 +12,24 @@ export const getApi = async <T>(
? url
: `${process.env.REACT_APP_API_DEFAULT + url}`;

const userToken = localStorage.getItem('userToken');
const headers: Headers = {
'Content-Type': 'application/json',
};

console.log(headers);
if (userToken) {
headers['Authorization'] = `Bearer ${userToken}`;
}

const response = await fetch(apiUrl, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: localStorage.getItem('access_token') || '',
},
headers: headers,
});

const responseData: T = await response.json();
if (response.status !== 200) {
//todo: status 상태별로 로그인 토큰 유효 검증
throw new Error('API 요청에 실패했습니다.');
}

Expand Down
23 changes: 18 additions & 5 deletions frontend/src/apis/postApi.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
interface Headers {
'Content-Type': string;
[key: string]: string;
}

export const postApi = async (url: string, data?: {}, contentType?: string) => {
await fetch(`${process.env.REACT_APP_API_DEFAULT + url}`, {
const userToken = localStorage.getItem('userToken');
const headers: Headers = {
'Content-type': `${contentType || 'application/json'}`,
};

if (userToken) {
headers['Authorization'] = `Bearer ${userToken}`;
}

const response = await fetch(`${process.env.REACT_APP_API_DEFAULT + url}`, {
method: 'POST',
headers: {
'Content-type': `${contentType || 'application/json'}`,
Authorization: `Bearer ${localStorage.getItem('userToken') || ''}`,
},
headers: headers,
body: JSON.stringify(data),
});

return response;
};
4 changes: 2 additions & 2 deletions frontend/src/components/AddFavorite/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { styled } from 'styled-components';
import { postApi } from '../../apis/postApi';
import useToast from '../../hooks/useToast';
import { useState } from 'react';

interface AddFavoriteProps {
id: number;
Expand All @@ -17,8 +16,9 @@ const AddFavorite = ({ id, children }: AddFavoriteProps) => {
// TODO : post 후 전역 favorite List 에 담기, toast 메세지 수정
// await postApi('',{});
// await getApi('');
await postApi(`/bookmarks/topics?id=${id}`, {});

showToast('info', '준비중인 기능입니다.');
showToast('info', '즐겨찾기에 추가되었습니다.');
};

return <Wrapper onClick={addFavoriteList}>{children}</Wrapper>;
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/Modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface ModalProps {
children: React.ReactNode;
top?: string;
left?: string;
overflow?: string;
}

const Modal = ({
Expand All @@ -27,6 +28,7 @@ const Modal = ({
children,
top,
left,
overflow,
}: ModalProps) => {
const { modalOpens, closeModal } = useContext(ModalContext);

Expand Down Expand Up @@ -63,6 +65,7 @@ const Modal = ({
height={height}
top={top}
left={left}
overflow={overflow}
>
{children}
</Wrapper>
Expand Down Expand Up @@ -119,6 +122,7 @@ const getModalPosition = (position: 'center' | 'bottom' | 'absolute') => {
transform: translate(-50%, -50%);
border-radius: ${({ theme }) => theme.radius.medium};
animation: ${openModalAnimation} 0.3s ease 1;
overflow: scroll;
`;

case 'bottom':
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/components/TopicCardList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import useToast from '../../hooks/useToast';

const TopicCardList = () => {
const [topics, setTopics] = useState<TopicType[]>([]);
const { markers, removeMarkers } = useContext(MarkerContext);
const { markers, removeMarkers, removeInfowindows } =
useContext(MarkerContext);
const { state: url } = useLocation();
const { showToast } = useToast();

Expand All @@ -30,7 +31,10 @@ const TopicCardList = () => {

useEffect(() => {
getAndSetDataFromServer();
if (markers.length > 0) removeMarkers();
if (markers.length > 0) {
removeMarkers();
removeInfowindows();
}
}, []);

return (
Expand Down
83 changes: 83 additions & 0 deletions frontend/src/components/common/CheckBox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { useState } from 'react';
import styled from 'styled-components';
import Flex from '../Flex';

interface CheckboxProps {
id: number;
isAlreadyChecked: boolean;
label: string;
onChecked: (checked: boolean, id: number) => void;
}

const Checkbox = ({
id,
isAlreadyChecked,
label,
onChecked,
}: CheckboxProps) => {
const [isChecked, setIsChecked] = useState(isAlreadyChecked);

const updateCheckedMembers = () => {
const updatedChecked = !isChecked;
console.log(updatedChecked);
setIsChecked(updatedChecked);
onChecked(updatedChecked, id);
};

return (
<CheckboxWrapper key={id}>
<Label htmlFor={label}>
<Flex $justifyContent="space-between" width="100%">
<span>{label}</span>
<CheckboxInput
type="checkbox"
id={label}
checked={isChecked}
onChange={updateCheckedMembers}
/>
</Flex>
</Label>
</CheckboxWrapper>
);
};

const CheckboxWrapper = styled(Flex)`
border-bottom: 1px solid #c6c6c6;
margin-bottom: 20px;
&:last-child {
border-bottom: none;
margin-bottom: 0;
}
`;

const Label = styled.label`
cursor: pointer;
display: flex;
align-items: center;
width: 100%;
`;

const CheckboxInput = styled.input`
-webkit-appearance: none;
appearance: none;
width: 1.6em;
height: 1.6em;
border-radius: 0.15em;
margin-right: 0.5em;
border: 0.15em solid ${({ theme }) => theme.color.primary};
background-color: ${({ theme }) => theme.color.white};
outline: none;
cursor: pointer;
&:checked {
border-color: transparent;
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M5.707 7.293a1 1 0 0 0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0-1.414-1.414L7 8.586 5.707 7.293z'/%3e%3c/svg%3e");
background-size: 100% 100%;
background-position: 50%;
background-repeat: no-repeat;
background-color: ${({ theme }) => theme.color.primary};
}
`;

export default Checkbox;
31 changes: 31 additions & 0 deletions frontend/src/context/MarkerContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ type MarkerContextType = {
clickedMarker: any;
createMarkers: (map: any) => void;
removeMarkers: () => void;
removeInfowindows: () => void;
createInfowindows: (map: any) => void;
displayClickedMarker: (map: any) => void;
};

Expand All @@ -18,6 +20,8 @@ export const MarkerContext = createContext<MarkerContextType>({
createMarkers: () => {},
removeMarkers: () => {},
displayClickedMarker: () => {},
removeInfowindows: () => {},
createInfowindows: () => {},
});

interface Props {
Expand All @@ -26,6 +30,7 @@ interface Props {

const MarkerProvider = ({ children }: Props): JSX.Element => {
const [markers, setMarkers] = useState<any>([]);
const [infoWindows, setInfoWindows] = useState<any>([]);
const [clickedMarker, setClickedMarker] = useState<any>(null);
const { coordinates, clickedCoordinate } = useContext(CoordinatesContext);
const { topicId } = useParams<{ topicId: string }>();
Expand Down Expand Up @@ -82,17 +87,43 @@ const MarkerProvider = ({ children }: Props): JSX.Element => {
setMarkers(newMarkers);
};

const createInfowindows = (map: any) => {
const newInfowindows = coordinates.map((coordinate: any) => {
const infoWindow = new window.Tmapv3.InfoWindow({
position: new window.Tmapv3.LatLng(
coordinate.latitude,
coordinate.longitude,
),

content: coordinate.pinName,
offset: new window.Tmapv3.Point(0, -60),
type: 2,
map: map,
});
return infoWindow;
});

setInfoWindows(newInfowindows);
};

const removeMarkers = () => {
markers.forEach((marker: any) => marker.setMap(null));
setMarkers([]);
};

const removeInfowindows = () => {
infoWindows.forEach((infowindow: any) => infowindow.setMap(null));
setInfoWindows([]);
};

return (
<MarkerContext.Provider
value={{
clickedMarker,
markers,
removeMarkers,
removeInfowindows,
createInfowindows,
createMarkers,
displayClickedMarker,
}}
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/hooks/useUpdateCoordinates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ interface UseUpdateCoordinatesProps {

export default function useUpdateCoordinates(map: UseUpdateCoordinatesProps) {
const { coordinates } = useContext(CoordinatesContext);
const { markers, createMarkers, removeMarkers } = useContext(MarkerContext);
const { markers, createMarkers, removeMarkers, createInfowindows } =
useContext(MarkerContext);

useEffect(() => {
if (!map) return;
Expand All @@ -17,6 +18,7 @@ export default function useUpdateCoordinates(map: UseUpdateCoordinatesProps) {
}
if (coordinates.length > 0) {
createMarkers(map);
createInfowindows(map);
}
}, [coordinates]);
}
14 changes: 6 additions & 8 deletions frontend/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@ const root = ReactDOM.createRoot(rootElement);
// }

root.render(
<StrictMode>
<ThemeProvider theme={theme}>
<AbsoluteModalContextProvider>
<GlobalStyle />
<App />
</AbsoluteModalContextProvider>
</ThemeProvider>
</StrictMode>,
<ThemeProvider theme={theme}>
<AbsoluteModalContextProvider>
<GlobalStyle />
<App />
</AbsoluteModalContextProvider>
</ThemeProvider>,
);
1 change: 0 additions & 1 deletion frontend/src/pages/KaKaoRedirectPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useLocation } from 'react-router-dom';
import { getApi } from '../apis/getApi';
import { keyframes, styled } from 'styled-components';
import useNavigator from '../hooks/useNavigator';
import { LoginResponse } from '../types/Login';

export const handleOAuthKakao = async (code: string) => {
try {
Expand Down
Loading

0 comments on commit f892740

Please sign in to comment.