Skip to content

Commit

Permalink
Merge pull request #16 from JupGo/diary/12
Browse files Browse the repository at this point in the history
[feat] 나무 상세 화면 구현
  • Loading branch information
yunsun99 authored Mar 1, 2023
2 parents 3c211ae + a58f0e1 commit d68e2ee
Show file tree
Hide file tree
Showing 39 changed files with 1,029 additions and 37 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
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
Binary file added public/IcArrowLeft.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/_redirects
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/* /index.html 200
10 changes: 6 additions & 4 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<meta name="description" content="Web site created using create-react-app" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100;300;400;500;700;900&display=swap" rel="stylesheet" />

<script
type="text/javascript"
src="//dapi.kakao.com/v2/maps/sdk.js?appkey=d2be9d6e5ecbac239e72d3896c0d4363"></script>
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
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
9 changes: 9 additions & 0 deletions src/asset/icon/IcAlbum.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/IcBackBtn.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/asset/icon/IcCamera.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/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.
9 changes: 9 additions & 0 deletions src/asset/icon/IcMainDefault.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.
9 changes: 9 additions & 0 deletions src/asset/icon/IcSubDefault.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/asset/icon/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
export { ReactComponent as IcAlbum } from './IcAlbum.svg';
export { ReactComponent as IcBackBtn } from './IcBackBtn.svg';
export { ReactComponent as IcCamera } from './IcCamera.svg';
export { ReactComponent as IcFloggingStart } from './IcFlogging.svg';
export { ReactComponent as IcLogo } from './IcLogo.svg';
export { ReactComponent as IcMainDefault } from './IcMainDefault.svg';
export { ReactComponent as IcTemporaryPause } from './IcPause.svg';
export { ReactComponent as IcRunning } from './IcRunning.svg';
export { ReactComponent as IcStop } from './IcStop.svg';
export { ReactComponent as IcSubDefault } from './IcSubDefault.svg';
Binary file added src/asset/image/subDefaultImg1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/asset/image/subDefaultImg2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/asset/image/subDefaultImg3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/asset/image/subDefaultImg4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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;
`;
39 changes: 39 additions & 0 deletions src/components/map/KakaoMap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useEffect, useState } from 'react';
import styled from 'styled-components';

import { KakaoMapInfo } from '../../types/map';

const KakaoMap = () => {
const [map, setMap] = useState({});
const [kakaoMapInfo, setKakaoMapInfo] = useState<KakaoMapInfo>();
const { kakao } = window;

useEffect(() => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
setKakaoMapInfo({ latitude: position.coords.latitude, longitude: position.coords.longitude });
});
}
}, []);
useEffect(() => {
if (kakaoMapInfo) {
const container = document.getElementById('map');
const options = {
center: new kakao.maps.LatLng(kakaoMapInfo.latitude, kakaoMapInfo.longitude),
level: 3,
};

setMap(new kakao.maps.Map(container, options));
}
}, [kakaoMapInfo]);

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

export default KakaoMap;

const StMapWrapper = styled.div`
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};
}
`;
2 changes: 2 additions & 0 deletions src/components/map/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +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;
Loading

0 comments on commit d68e2ee

Please sign in to comment.