diff --git a/README.md b/README.md index 7783111..f112d90 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # up-d4te > This is the recommend dating course in korea with CLI.
-> This project is made by [ink](https://github.com/vadimdemedes/ink), you can own cli project with it.
+> This project is made by [ink](https://github.com/vadimdemedes/ink), you can make your own cli project with it.
> You can see project repository [here](https://github.com/gdsc-ssu/up-date-cli). ## Install diff --git a/package.json b/package.json index ad84520..75d6a6e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "up-d4te", - "version": "0.0.10", + "version": "0.0.12", "description": "Recommend Dating Course in Korea with CLI", "author": { "name": "Sanghyeon Sim", diff --git a/source/Login.js b/source/Login.js index 98a642c..fbff476 100644 --- a/source/Login.js +++ b/source/Login.js @@ -2,34 +2,48 @@ import React, {useState} from 'react'; import {Text, Box, useInput} from 'ink'; import TextInput from 'ink-text-input'; import theme from './Theme.js'; +import {getLoginCheck} from './api/remote.js'; const Login = ({userId, setId, setShow}) => { const [nextStepInfo, setNextStepInfo] = useState(false); const [eMail, setEMail] = useState(''); const [loginSuccess, setLoginSuccess] = useState(true); + const [isLoading, setIsLoading] = useState(false); useInput((input, key) => { if (!key) return; if (key.return) { if (nextStepInfo) { - if (userId === 'hoyeon' && eMail == 'hello') { - setShow(true); - } else { - setId(''); - setEMail(''); - setLoginSuccess(false); - } + setIsLoading(true); + setEMail(''); + let tempUserId = userId; + + getLoginCheck(userId, eMail).then(res => { + if (res.data['statusCode'] == 200) { + setShow(true); + // 로그인 중 아이디 변경 방지 + setId(tempUserId); + } else { + setId(''); + setEMail(''); + setLoginSuccess(false); + setIsLoading(false); + } + }); } setNextStepInfo(!nextStepInfo); - } else if (input === 'c') { - process.exit(0); + } + + if (key.escape) { + process.exit(); } }); return ( + {isLoading ? Loading... : ''} {loginSuccess ? '' : ID or EMail is wrong} ID: diff --git a/source/Register.js b/source/Register.js index cdb3bac..5ff837d 100644 --- a/source/Register.js +++ b/source/Register.js @@ -2,11 +2,12 @@ import React, {useState} from 'react'; import {Text, Box, useInput} from 'ink'; import TextInput from 'ink-text-input'; import theme from './Theme.js'; +import {postRegister} from './api/remote.js'; const Register = ({setIsSelected, setSpaceStep}) => { const [nextStepInfo, setNextStepInfo] = useState(0); - const [Id, setId] = useState(''); - const [Password, setPassword] = useState(''); + const [userId, setUserId] = useState(''); + const [eMail, setEMail] = useState(''); const [girlfriend, setGirlfriend] = useState(''); const [openMessage, setOpenMessage] = useState(''); @@ -17,6 +18,7 @@ const Register = ({setIsSelected, setSpaceStep}) => { if (nextStepInfo === 2) { setSpaceStep('login'); setIsSelected(true); + postRegister(userId, eMail); } setNextStepInfo(nextStepInfo + 1); } @@ -34,21 +36,21 @@ const Register = ({setIsSelected, setSpaceStep}) => { NEW ID: {nextStepInfo === 0 ? ( - + ) : ( - {Id} + {userId} )} {nextStepInfo === 1 ? ( <> NEW EMAIL: - + ) : nextStepInfo === 2 ? ( <> NEW EMAIL: - {Password} + {eMail} ) : ( '' diff --git a/source/Search.js b/source/Search.js index edd2500..12e870d 100644 --- a/source/Search.js +++ b/source/Search.js @@ -47,7 +47,7 @@ const Search = ({setlist, setStation, setId, setStoreName, setSingleShop}) => { } } - if (minDistance <= 2) { + if (minDistance <= 1) { return `Command not found. Did you mean "${closestCommand}"?`; } @@ -60,14 +60,16 @@ const Search = ({setlist, setStation, setId, setStoreName, setSingleShop}) => { if (key.return) { setPreviousCommand(search); if (search === 'ls') { - setlist(list => [...list, [data.location, search]]); + setlist(list => [...list, [data.locations, search]]); setSearch(''); return; } if (search.startsWith('cd ')) { - let station = search.slice(3, search.length); - setlist(list => [...list, [[], search]]); - setStation(station); + let station = search.slice(3, search.length).trim(); + if (data.locations.includes(station)) { + setlist(list => [...list, [[], search]]); + setStation(station); + } setSearch(''); return; } diff --git a/source/SearchContainer.js b/source/SearchContainer.js index 7c76187..4cc20cf 100644 --- a/source/SearchContainer.js +++ b/source/SearchContainer.js @@ -44,7 +44,7 @@ const SearchContainer = ({userId}) => { singleShop={singleShop} /> ) : storeName ? ( - + ) : ( [...list, [[], `${station} 술집`]]); } getAllPlaceCheck(1, station).then(res => { - setShops(res.data.body); // shoplist.slice(first, last) + if (res.data['statusCode'] == 404) { + setShops([]); + } else { + setShops(res.data.body); + } }); setStation(''); } diff --git a/source/api/remote.js b/source/api/remote.js index 298fc04..a605129 100644 --- a/source/api/remote.js +++ b/source/api/remote.js @@ -12,4 +12,44 @@ const getSinglePlaceCheck = placeId => UpdateAxios.get(`/place/${placeId}`); const getReviewCheck = placeId => UpdateAxios.get(`/review/place/${placeId}?page=1`); -export {getAllPlaceCheck, getSinglePlaceCheck, getReviewCheck}; +const postShop = ( + userId, + name, + phoneNumber, + location, + start_at, + end_at, + latitude, + longitude, + url, + menu, +) => + UpdateAxios.post(`/place/user/${userId}`, { + name, + phoneNumber, + location, + start_at, + end_at, + latitude, + longitude, + url, + menu, + }); + +const getLoginCheck = (userId, eMail) => + UpdateAxios.get(`/user/${userId}?email=${eMail}`); + +const postRegister = (userId, eMail) => + UpdateAxios.post(`/user`, { + id: userId, + email: eMail, + }); + +export { + getAllPlaceCheck, + getSinglePlaceCheck, + postShop, + getLoginCheck, + postRegister, + getReviewCheck, +}; diff --git a/source/component/EachShop.js b/source/component/EachShop.js index b4e6371..71a4235 100644 --- a/source/component/EachShop.js +++ b/source/component/EachShop.js @@ -38,10 +38,7 @@ const EachShop = ({data, key, isEnd}) => { - - "starRate" : "{data.averageStar}", - - + "starRate" : "{data.averageStar}" {isEnd ? '}' : '},'} diff --git a/source/component/ListShop.js b/source/component/ListShop.js index 5d34f3f..32b2b59 100644 --- a/source/component/ListShop.js +++ b/source/component/ListShop.js @@ -3,52 +3,65 @@ import {Text, Box, Newline, Spacer} from 'ink'; import theme from '../Theme.js'; import TextInput from 'ink-text-input'; import EachShop from './EachShop.js'; +import shoplist from '../examples/shoplist.js'; const ListShop = ({shops, setShops, setType}) => { let first = 0; let last = 3; const [confirmCommand, setConfirmCommand] = useState(''); const loadMore = () => { + // if (shops) setShops([...shops, ...shoplist.slice(first + 3, last + 3)]); }; return ( - - {'['} - - {shops.map((data, index, key) => ( - - ))} - - {']'} - - - - - Commands - - - :q - quit - / - :lm - load more reviews + <> + + {shops.length === 0 ? ( + + Status code: 404 + 검색 결과가 없습니다. + + ) : ( + + {'['} + + {shops.map((data, index) => ( + + ))} + + {']'} + + )} + + + + + + Commands + + + :q - quit + / + :lm - load more reviews + + { + if (confirmCommand == ':q') { + setType(''); + } else if (confirmCommand == ':lm') { + loadMore(); + setConfirmCommand(''); + } else { + setConfirmCommand(''); + } + }} + /> - { - if (confirmCommand == ':q') { - //TODO : 저장하고 종료 - setType(''); - } else if (confirmCommand == ':lm') { - loadMore(); - setConfirmCommand(''); - } else { - setConfirmCommand(''); - } - }} - /> - + ); }; diff --git a/source/component/ShopDetail.js b/source/component/ShopDetail.js index 25e8b7f..5b47cb0 100644 --- a/source/component/ShopDetail.js +++ b/source/component/ShopDetail.js @@ -2,36 +2,16 @@ import React, {useState} from 'react'; import {Text, Newline, Box, Spacer, useInput} from 'ink'; import TextInput from 'ink-text-input'; import theme from '../Theme.js'; -import SingleShop from './SingleShop.js'; const ShopDetail = ({id, setId, userId, singleShop}) => { - const initialData = { - id: '1', - title: 'The 5th Wave', - location: '서울시 동작구 상도로 369', - nearStation: '상도역', - openTime: '09:00', - closeTime: '22:00', - menu: [ - { - name: '카페라떼', - price: 4000, - }, - ], - starRate: 4.5, - reviews: [ - {writer: 'hoyeon', content: 'good', starRate: 5}, - {writer: 'hoyeon', content: '맛있네요', starRate: 3}, - ], - }; - const [data, setData] = useState(singleShop); const [command, setCommand] = useState(''); const [isAddReview, setIsAddReview] = useState(false); + const [content, setContent] = useState(''); - const [rate, setRate] = useState(5); + const [star, setStar] = useState(5); const onCommandSubmit = () => { if (command === ':q') { @@ -47,9 +27,9 @@ const ShopDetail = ({id, setId, userId, singleShop}) => { const updatedReviews = [ ...data.reviews, { - writer: 'hoyeon', + userId: 'hoyeon', content: 'content', - starRate: 3, + star: 3, }, ]; setData({...data, reviews: updatedReviews}); @@ -61,29 +41,29 @@ const ShopDetail = ({id, setId, userId, singleShop}) => { useInput((input, key) => { if (isAddReview) { - if (key.upArrow && rate < 5) { - setRate(prevRate => prevRate + 1); - } else if (key.downArrow && rate > 1) { - setRate(prevRate => prevRate - 1); + if (key.upArrow && star < 5) { + setStar(prevRate => prevRate + 1); + } else if (key.downArrow && star > 1) { + setStar(prevRate => prevRate - 1); } } }); const onReivewSubmit = () => { // TODO : add review - setIsAddReview(false); const updatedReviews = [ ...data.reviews, { - writer: userId, + userId: userId, content: content, - starRate: rate, + star: star, }, ]; setData({...data, reviews: updatedReviews}); setContent(''); - setRate(5); + setStar(5); + setIsAddReview(false); }; return ( @@ -122,7 +102,7 @@ const ShopDetail = ({id, setId, userId, singleShop}) => { " - "starRate" : {rate} + "starRate" : {star} "helpText" : "⬆️ / ⬇️ to set rating" @@ -165,7 +145,7 @@ const ShopView = ({data}) => { {data.menu.map((item, index, array) => ( - {' '} + {' '} {'{'} "{item.menuName}" : {item.menuPrice} {'}'} {index !== array.length - 1 ? ',' : ''} @@ -176,7 +156,7 @@ const ShopView = ({data}) => { - "starRate" : "{starRateString}({data.averageStar})", + "starRate" : "{starRateString} ({data.averageStar})", {data.reviews.length > 0 ? ( diff --git a/source/component/ShopPost.js b/source/component/ShopPost.js index 8ab1cf1..a6f81e4 100644 --- a/source/component/ShopPost.js +++ b/source/component/ShopPost.js @@ -2,6 +2,7 @@ import React, {useState} from 'react'; import {Text, Box, useInput, Newline, Spacer} from 'ink'; import TextInput from 'ink-text-input'; import {fetchKakaoShops} from '../api/kakao.js'; +import {postShop} from '../api/remote.js'; const dayContainer = (isFocused, isSelected, day, key) => { var color = 'white'; @@ -41,7 +42,7 @@ const editContainer = (isFocused, text, key) => { * 카테고리는 cafe, restaurant로 구분된다. * 이외의 카테고리나 넣지 않으면 모든 카테고리에서 검색한다. */ -const ShopPost = ({category, setStoreName}) => { +const ShopPost = ({userId, category, setStoreName}) => { const [lastKeyPress, setLastKeyPress] = useState(null); const [inputStep, setInputStep] = useState(0); // 0: title, 1: openTime, 2: closeTime @@ -70,6 +71,12 @@ const ShopPost = ({category, setStoreName}) => { const [isEdit, setIsEdit] = useState(false); // 입력 수정 const editList = ['title', 'openDay', 'openTime', 'closeTime', 'menu', '']; // 수정 가능한 목록 + //Kakao map api data + const [phoneNumber, setPhoneNumber] = useState(''); + const [latitude, setLatitude] = useState(0); + const [longitude, setLongitude] = useState(0); + const [placeUrl, setPlaceUrl] = useState(''); + useInput((input, key) => { if (!key) return; setLastKeyPress(key.name); @@ -270,6 +277,10 @@ const ShopPost = ({category, setStoreName}) => { } const response = await fetchKakaoShops(shopTitle, category); setKakaoShops(response.data['documents']); + setLatitude(response.data['documents'][0].y); + setLongitude(response.data['documents'][0].x); + setPhoneNumber(response.data['documents'][0].phone); + setPlaceUrl(response.data['documents'][0].place_url); setSelectedShopIndex(0); }; @@ -460,7 +471,26 @@ const ShopPost = ({category, setStoreName}) => { focus={!isEdit} onSubmit={() => { if (confirmCommand == ':wq') { - //TODO : 저장하고 종료 + postShop( + userId, + shopTitle, + phoneNumber, + kakaoShops[selectedShopIndex].address_name, + `${openTimeHour + .toString() + .padStart(2, '0')}:${openTimeMinute + .toString() + .padStart(2, '0')}`, + `${closeTimeHour + .toString() + .padStart(2, '0')}:${closeTimeMinute + .toString() + .padStart(2, '0')}`, + latitude, + longitude, + placeUrl, + menuList, + ); setStoreName(''); } else if (confirmCommand == ':q!') { setStoreName(''); diff --git a/source/examples/location.js b/source/examples/location.js index c37a8af..6e86852 100644 --- a/source/examples/location.js +++ b/source/examples/location.js @@ -1,14 +1,204 @@ export default { - location: [ - '신촌', - '건대 입구', - '숭실대 입구', + locations: [ + '가락시장', + '가산디지털단지', '강남', - '홍대', - '신림', - '신도림', - '서울대입구', + '강남구청', + '강동', + '강동구청', + '강변', + '강일', + '개롱', + '개화산', + '거여', + '건대입구', + '경복궁', + '경찰병원', + '고덕', + '고려대', + '고속터미널', + '공덕', + '공릉', + '광나루', + '광명사거리', + '광화문', + '광흥창', + '교대', + '구로디지털단지', + '구산', + '구의', + '구파발', + '군자', + '굽은다리', + '금호', + '길동', + '길음', + '김포공항', + '까치산', + '낙성대', + '남구로', + '남부터미널', + '남성', + '남위례', + '남태령', + '남한산성입구', + '내방', + '노원', + '녹번', + '녹사평', + '논현', + '단대오거리', + '답십리', + '당고개', + '당산', + '대림', + '대청', + '대치', + '대흥', + '도곡', + '도림천', + '도봉산', + '독립문', + '독바위', + '돌곶이', + '동대문', + '동대문역사문화공원', + '동대입구', + '동묘앞', + '동작', + '둔촌동', + '둔촌오륜역', + '디지털미디어시티', + '뚝섬', + '뚝섬유원지', + '마곡', + '마들', + '마장', + '마천', + '마포', + '마포구청', + '망원', + '매봉', + '먹골', + '면목', + '명동', + '명일', + '모란', + '목동', + '몽촌토성', + '무악재', + '문래', + '문정', + '미사', + '미아', + '미아사거리', + '반포', + '발산', + '방배', + '방이', + '방화', + '버티고개', + '보라매', + '보문', + '복정', + '봉은사역', + '봉천', + '봉화산', + '불광', + '사가정', + '사당', + '산성', + '삼각지', + '삼성', + '삼성중앙역', + '삼전역', + '상계', + '상도', '상봉', - '천호', + '상수', + '상왕십리', + '상월곡', + '상일동', + '새절', + '서대문', + '서울', + '서울대입구', + '서초', + '석계', + '석촌', + '석촌고분역', + '석촌역', + '선릉', + '선정릉역', + '성수', + '성신여대입구', + '송정', + '송파', + '송파나루역', + '수락산', + '수서', + '수유', + '수진', + '숙대입구', + '숭실대입구', + '시청', + '신금호', + '신길', + '신내', + '신답', + '신당', + '신대방', + '신대방삼거리', + '신도림', + '신림', + '신사', + '신설동', + '신용산', + '신정', + '신정네거리', + '신촌', + '신풍', + '신흥', + '쌍문', + '아차산', + '아현', + '안국', + '안암', + '암사', + '압구정', + '애오개', + '약수', + '양재', + '양천구청', + '양평', + '어린이대공원', + '언주역', + '여의나루', + '여의도', + '역삼', + '역촌', + '연신내', + '영등포구청', + '영등포시장', + '오금', + '오목교', + '옥수', + '온수', + '올림픽공원', + '올림픽공원역', + '왕십리', + '용답', + '용두', + '용마산', + '우장산', + '월곡', + '월드컵경기장', + '을지로3가', + '을지로4가', + '을지로입구', + '응암', + '이대', + '이촌', + '이태원', ], };