Skip to content

Commit

Permalink
Merge pull request #9 from JupGo/map/8
Browse files Browse the repository at this point in the history
[ 🗺 Map ] UI 완성 후 타이머기능까지 연결하기
  • Loading branch information
Happhee authored Feb 1, 2023
2 parents 7b3a616 + a6e746a commit c19ac37
Show file tree
Hide file tree
Showing 22 changed files with 329 additions and 35 deletions.
1 change: 0 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
"import"
],
"rules": {
"indent": ["error", 2, { "SwitchCase": 1 }], // 들여쓰기 몇 칸? 기본 2칸으로 하되, switch문에서는 1칸으로 지정
"quotes": ["off", "single"], // 쌍따옴표가 아닌 홑따옴표를 사용
"semi": ["error", "always"], // semi colon을 강제함
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 0 }],
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
"react-dom": "^18.2.0",
"react-router-dom": "^6.4.3",
"react-scripts": "5.0.1",
"recoil": "^0.7.6",
"recoil-persist": "^4.2.0",
"styled-components": "^5.3.6",
"typescript": "^4.4.2",
"web-vitals": "^2.1.0"
Expand Down
16 changes: 1 addition & 15 deletions public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,7 @@
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}

],
"start_url": ".",
"display": "standalone",
Expand Down
3 changes: 3 additions & 0 deletions src/asset/icon/IcFlogging.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/asset/icon/IcJupgoLogo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/asset/icon/IcPause.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/asset/icon/IcRunning.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/asset/icon/IcStop.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/asset/icon/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export { ReactComponent as IcFloggingStart } from './IcFlogging.svg';
export { ReactComponent as IcLogo } from './IcLogo.svg';
export { ReactComponent as IcTemporaryPause } from './IcPause.svg';
export { ReactComponent as IcRunning } from './IcRunning.svg';
export { ReactComponent as IcStop } from './IcStop.svg';
29 changes: 16 additions & 13 deletions src/components/common/Router.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { RecoilRoot } from 'recoil';

import Authentication from '../../pages/Authentication';
import DiaryDetail from '../../pages/DiaryDetail';
Expand All @@ -12,19 +13,21 @@ import TreeDiary from '../../pages/TreeDiary';
const Router = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Main />} />
<Route path="*" element={<Error404 />} />
<Route path="/treediary" element={<TreeDiary />}>
<Route path="detail" element={<DiaryDetail />} />
<Route path="detailall" element={<DiaryDetailAll />} />
</Route>
<Route path="/map" element={<Map />}>
<Route path="authentication" element={<Authentication />} />
</Route>
<Route path="/login" element={<Login />} />
<Route path="/mypage" element={<Mypage />} />
</Routes>
<RecoilRoot>
<Routes>
<Route path="/" element={<Main />} />
<Route path="*" element={<Error404 />} />
<Route path="/treediary" element={<TreeDiary />}>
<Route path="detail" element={<DiaryDetail />} />
<Route path="detailall" element={<DiaryDetailAll />} />
</Route>
<Route path="/map" element={<Map />}>
<Route path="authentication" element={<Authentication />} />
</Route>
<Route path="/login" element={<Login />} />
<Route path="/mypage" element={<Mypage />} />
</Routes>
</RecoilRoot>
</BrowserRouter>
);
};
Expand Down
45 changes: 45 additions & 0 deletions src/components/map/JupgoButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';
import styled from 'styled-components';

import { IcFloggingStart, IcStop, IcTemporaryPause } from '../../asset/icon';

interface JupgoButtonProps {
btnType: string;
handleBtnClick: React.MouseEventHandler;
}

const JupgoButton = (props: JupgoButtonProps) => {
const { btnType, handleBtnClick } = props;

return (
<JupgoBtn onClick={handleBtnClick} btnType={btnType}>
{btnType === 'floggingPause' ? (
<IcTemporaryPause />
) : btnType === 'floggingStart' ? (
<IcFloggingStart />
) : (
<IcStop />
)}
</JupgoBtn>
);
};

export default JupgoButton;

const JupgoBtn = styled.button<{ btnType: string }>`
display: flex;
justify-content: center;
align-items: center;
width: 45%;
height: 100%;
background-color: ${({ theme, btnType }) =>
btnType === 'floggingPause'
? theme.colors.gray_01
: btnType === 'floggingStart'
? theme.colors.green_dark
: theme.colors.pink};
border: none;
border-radius: 2rem;
`;
10 changes: 6 additions & 4 deletions src/components/map/KakaoMap.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, useEffect, useRef, useState } from 'react';
import { useEffect, useState } from 'react';
import styled from 'styled-components';

import { KakaoMapInfo } from '../../types/map';
Expand Down Expand Up @@ -26,12 +26,14 @@ const KakaoMap = () => {
setMap(new kakao.maps.Map(container, options));
}
}, [kakaoMapInfo]);
return kakaoMapInfo != undefined ? <StMapWrapper id="map"></StMapWrapper> : <div>lodiing중...</div>;

if (!kakaoMapInfo) return <div>Loading중...</div>;
return <StMapWrapper id="map" />;
};

export default KakaoMap;

const StMapWrapper = styled.div`
width: 39rem;
height: 84.4rem;
width: 100%;
height: 100%;
`;
106 changes: 106 additions & 0 deletions src/components/map/RunningControl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { useState } from 'react';
import { useRecoilState } from 'recoil';
import styled from 'styled-components';

import { IcRunning } from '../../asset/icon';
import useCouter from '../../lib/hooks/useCouter';
import { floggingInfoState } from '../../recoil/atom';
import { getDateParse } from '../../utils/dateParse';
import JupgoButton from './JupgoButton';

const RunningControl = () => {
const [isFloggingPause, setIsFloggintPause] = useState(false);
const [floggingInfo, setFloggingInfo] = useRecoilState(floggingInfoState);
const { count, start, stop } = useCouter(0, 1000);
const { distance, duration } = floggingInfo;

const handleFloggingStart = () => {
start();
setIsFloggintPause(!isFloggingPause);
};
const handleFloggingPause = () => {
stop();
setIsFloggintPause(!isFloggingPause);
};
const handleFloggingStop = () => {
stop();
setFloggingInfo({ ...floggingInfo });
};

return (
<RunningControlWrapper>
<HeaderWrapper>
<header>
<h1>{distance}</h1>
<h1>km</h1>
<IcRunning />
</header>
<p>{getDateParse(count).map((data, idx) => (idx !== 2 ? data + ' : ' : data))}</p>
</HeaderWrapper>

<article>
{isFloggingPause ? (
<JupgoButton btnType={'floggingPause'} handleBtnClick={handleFloggingPause} />
) : (
<JupgoButton btnType={'floggingStart'} handleBtnClick={handleFloggingStart} />
)}

<JupgoButton btnType={'floggingStop'} handleBtnClick={handleFloggingStop} />
</article>
</RunningControlWrapper>
);
};

export default RunningControl;

const RunningControlWrapper = styled.section`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 94%;
height: 14%;
padding: 4% 8%;
background-color: rgba(250, 250, 250, 0.9);
border-radius: 1rem;
article {
display: flex;
justify-content: space-between;
width: 100%;
height: 40%;
}
`;
const HeaderWrapper = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
header {
display: flex;
justify-content: flex-start;
align-items: center;
gap: 0.5rem;
& > h1 {
vertical-align: bottom;
${({ theme }) => theme.fonts.Jupgo_Bold_32}
:nth-child(2) {
font-size: 2rem;
}
}
}
p {
margin-right: 12%;
${({ theme }) => theme.fonts.Jupgo_Bold_20}
color:${({ theme }) => theme.colors.gray_01};
}
`;
1 change: 1 addition & 0 deletions src/components/map/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default as KakaoMap } from './KakaoMap';
export { default as RunningControl } from './RunningControl';
23 changes: 23 additions & 0 deletions src/lib/hooks/useCouter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useCallback, useRef, useState } from 'react';

const useCouter = (initMinutes: number, ms: number) => {
const [count, setCount] = useState(initMinutes);
const intervalRef = useRef<NodeJS.Timeout | null>(null);

const start = useCallback(() => {
if (intervalRef.current) return;
intervalRef.current = setInterval(() => {
setCount((prev) => prev + 1);
}, ms);
}, []);

const stop = useCallback(() => {
if (!intervalRef.current) return;
clearInterval(intervalRef.current);
intervalRef.current = null;
}, []);

return { count, start, stop };
};

export default useCouter;
37 changes: 35 additions & 2 deletions src/pages/Map.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,42 @@
import React from 'react';
import styled from 'styled-components';

import { KakaoMap } from '../components/map';
import { IcLogo } from '../asset/icon';
import { KakaoMap, RunningControl } from '../components/map';

const Map = () => {
return <KakaoMap />;
return (
<StMapWrapper>
<KakaoMap />
<IcLogo />
<RunningControl />
</StMapWrapper>
);
};

export default Map;

const StMapWrapper = styled.div`
width: 100%;
height: 100%;
& > svg {
position: absolute;
top: 2rem;
left: 50%;
height: 3.064rem;
transform: translate(-50%, 0%);
z-index: 3;
}
& > section {
position: absolute;
bottom: 12%;
left: 50%;
transform: translate(-50%, 0%);
z-index: 3;
}
`;
18 changes: 18 additions & 0 deletions src/recoil/atom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { atom } from 'recoil';
import { recoilPersist } from 'recoil-persist';

import { FloggingData } from '../types/flogging';

const { persistAtom } = recoilPersist();

export const floggingInfoState = atom<FloggingData>({
key: 'floggingInfo',
default: {
date: '2023.01.12',
location: '인천',
distance: 0,
duration: '00:00:00',
photo: new FormData(),
},
effects_UNSTABLE: [persistAtom],
});
1 change: 1 addition & 0 deletions src/styles/style.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ declare module 'styled-components' {
};
fonts: {
Jupgo_Bold_32: SerializedStyles;
Jupgo_Bold_20: SerializedStyles;
Jupgo_SemiBold_32: SerializedStyles;
Jupgo_Regular_32: SerializedStyles;
};
Expand Down
Loading

0 comments on commit c19ac37

Please sign in to comment.