diff --git a/src/assets/svg.js b/src/assets/svg.js index f68d93f..2c7a21d 100644 --- a/src/assets/svg.js +++ b/src/assets/svg.js @@ -83,12 +83,12 @@ export const svgXml = { `, - starFill:` + starFill: ` `, - starEmpty:` + starEmpty: ` @@ -294,5 +294,11 @@ export const svgXml = { `, + close: ` + + + + + `, }, }; diff --git a/src/components/ListModal.js b/src/components/ListModal.js index 5faac60..4af3573 100644 --- a/src/components/ListModal.js +++ b/src/components/ListModal.js @@ -39,7 +39,35 @@ import AppContext from './AppContext'; const windowWidth = Dimensions.get('window').width; export default function ListModal(props) { - const {visible, setVisible, title, value, setValue, valueList} = props; + const {visible, setVisible, title, value, setValue, valueList, setLocation} = + props; + + const getMyLocation = async () => { + const platformPermissions = PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION; + + try { + let result = await request(platformPermissions); + console.log(result); + } catch (err) { + console.warn(err); + } + + Geolocation.getCurrentPosition( + position => { + console.log(position.coords.latitude, position.coords.longitude); + const {latitude, longitude} = position.coords; + + setLocation({ + latitude: latitude, + longitude: longitude, + }); + }, + error => { + console.log(error.code, error.message); + }, + {enableHighAccuracy: true, timeout: 15000, maximumAge: 10000}, + ); + }; return ( { + onPress={async () => { + if (item == '가까운 순') { + getMyLocation(); + } setValue(item); }}> {item == value ? ( diff --git a/src/components/StoreCompo.js b/src/components/StoreCompo.js index 2f70fe4..28c7d1c 100644 --- a/src/components/StoreCompo.js +++ b/src/components/StoreCompo.js @@ -50,10 +50,10 @@ export default function StoreCompo(props) { { @@ -153,7 +153,7 @@ export default function StoreCompo(props) { fontSize: 11, color: COLOR_TEXT70GRAY, }}> - {storeData.firstReview.reviewer + ' 님'} + {storeData.representativeReviewContent.reviewer + ' 님'} - {storeData.firstReview.body} + {storeData.representativeReviewContent.body} ) : ( diff --git a/src/components/TodayPick.js b/src/components/TodayPick.js index 6b532f3..3ff4588 100644 --- a/src/components/TodayPick.js +++ b/src/components/TodayPick.js @@ -86,7 +86,7 @@ export default function TodayPick(props) { ref={scrollViewRef}> {todaysPick.map((pickData, index) => { return ( - + ); })} @@ -103,7 +103,7 @@ const styles = StyleSheet.create({ marginTop: 15, width: windowWidth - 32, padding: 12, - paddingHorizontal: 10, + paddingHorizontal: 0, backgroundColor: COLOR_WHITE, borderRadius: 10, shadowOffset: { @@ -116,6 +116,7 @@ const styles = StyleSheet.create({ }, todayPickTitle: { fontSize: 20, + paddingHorizontal: 10, color: COLOR_TEXT70GRAY, fontWeight: '700', }, diff --git a/src/navigation/BottomTabNavigator.js b/src/navigation/BottomTabNavigator.js index 888d4a9..913ffa1 100644 --- a/src/navigation/BottomTabNavigator.js +++ b/src/navigation/BottomTabNavigator.js @@ -29,7 +29,6 @@ import HomeScreen from '../screens/home/HomeScreen'; import ListMainScreen from '../screens/list/ListMainScreen'; import MapScreen from '../screens/map/MapScreen'; import MypageScreen from '../screens/mypage/MypageScreen'; -import SearchScreen from '../screens/map/SearchScreen'; import UserDataChangeScreen from '../screens/mypage/UserDataChangeScreen'; const BottomTab = createBottomTabNavigator(); @@ -94,7 +93,6 @@ function MapNavigator() { cardStyleInterpolator: customCardStyleInterpolator, }}> - ); } diff --git a/src/navigation/MainStackNavigator.js b/src/navigation/MainStackNavigator.js index 1d25653..e4c7f48 100644 --- a/src/navigation/MainStackNavigator.js +++ b/src/navigation/MainStackNavigator.js @@ -17,6 +17,7 @@ import CheckEmailScreen from '../screens/signup/CheckEmailScreen'; import ProfileSetScreen from '../screens/signup/ProfileSetScreen'; import CheckEmailScreen2 from '../screens/signup/CheckEmailScreen2'; import ResetPasswordScreen from '../screens/signup/ResetPasswordScreen'; +import SearchScreen from '../screens/detail/SearchScreen'; import BottomTabNavigator from './BottomTabNavigator'; @@ -56,6 +57,7 @@ export default function MainStackNavigator() { + { + initRecentSearch(); + }, []); + + const autocomplete = async inputString => { + console.log('검색어:', inputString); + try { + const params = { + query: inputString, + }; + + const queryString = new URLSearchParams(params).toString(); + + const response = await axios.get(`${AUTO_COMPLETE}?${queryString}`, { + headers: {Authorization: `Bearer ${context.accessToken}`}, + }); + + console.log('response:', response.data.results); + + setAutoCompleteData(response.data.results); + } catch (e) { + console.log('error', e); + } + }; + + const initRecentSearch = async () => { + try { + const response = await axios.get(`${API_URL}/v1/recents`, { + headers: {Authorization: `Bearer ${context.accessToken}`}, + }); + + console.log('response:', response.data.data.recentQueries); + + setRecentSearch(response.data.data.recentQueries); + } catch (e) { + if (axios.isAxiosError(e)) { + console.log('Axios error:', e.response ? e.response.data : e.message); + } else { + console.log('splash error', e.message); + } + } + }; + + const deleteRecentSearch = async query => { + try { + console.log('context.accessToken:', context.accessToken); + + const response = await axios.delete(`${API_URL}/v1/recents`, { + headers: {Authorization: `Bearer ${context.accessToken}`}, + data: {query: query}, + }); + + console.log('response:', response.data); + } catch (e) { + if (axios.isAxiosError(e)) { + console.log('Axios error:', e.response ? e.response.data : e.message); + } else { + console.log('splash error', e.message); + } + } + }; + + return ( + <> +
+ + + {/* 검색창 */} + + { + setSearch(searchText); + navigation.goBack(); + }} + style={{ + padding: 8, + }}> + + + { + setSearchText(text); + autocomplete(text); + }} + blurOnSubmit={false} + maxLength={200} + value={searchText} + onSubmitEditing={() => { + setSearch(searchText); + navigation.goBack(); + }} + textAlignVertical="center" + autoCapitalize="none" + autoComplete="off" + autoCorrect={false} + numberOfLines={1} + /> + + + + {/* 최근 검색어 부분 */} + {searchText.length == 0 ? ( + + + + 최근 검색어 + + { + console.log('최근 검색어 전부 삭제'); + setRecentSearch([]); + + for (let i = 0; i < recentSearch.length; i++) { + deleteRecentSearch(recentSearch[i].query); + } + }} + style={{marginLeft: 10}}> + + 전체 삭제 + + + + + + + + {recentSearch.map((item, index) => { + return ( + <> + { + console.log('press item:', item.query); + setSearch(item.query); + navigation.goBack(); + }}> + {item.query} + { + console.log('삭제'); + deleteRecentSearch(item.query); + setRecentSearch(prevQueries => + prevQueries.filter(q => q.query !== item.query), + ); + }}> + + + + + + + ); + })} + + + + ) : ( + + { + return ( + { + setSearch(item.org_display); + navigation.goBack(); + }}> + + {item.org_display} + + ); + }} + /> + + )} + + + ); +} + +const styles = StyleSheet.create({ + entire: { + flex: 1, + backgroundColor: COLOR_BACKGROUND, + alignItems: 'center', + }, + textInput: { + marginLeft: 10, + flex: 1, + fontSize: 12, + color: COLOR_TEXT_BLACK, + padding: 0, + }, + recentHeader: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + marginHorizontal: 16, + width: windowWidth - 32, + // backgroundColor: 'blue', + }, + filterButton: { + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + padding: 3, + paddingHorizontal: 7, + borderRadius: 15, + backgroundColor: COLOR_PRIMARY, + height: 24, + }, + recentText: { + fontSize: 12, + color: COLOR_WHITE, + marginRight: 5, + }, + searchArea: { + // backgroundColor: 'blue', + flex: 1, + width: windowWidth, + }, + touchArea: { + // backgroundColor: 'blue', + flex: 1, + width: windowWidth, + }, + listButton: { + // backgroundColor: 'blue', + padding: 8, + paddingHorizontal: 16, + flexDirection: 'row', + }, + buttonText: { + fontSize: 12, + color: COLOR_TEXT_BLACK, + fontWeight: 'normal', + marginLeft: 2, + }, +}); diff --git a/src/screens/home/HomeScreen.js b/src/screens/home/HomeScreen.js index b0e7839..1e2741f 100644 --- a/src/screens/home/HomeScreen.js +++ b/src/screens/home/HomeScreen.js @@ -44,103 +44,7 @@ export default function HomeScreen() { const navigation = useNavigation(); const context = useContext(AppContext); - const [todaysPick, setTodaysPick] = useState([ - { - categories: [], - detailInfo: { - address: '경기 수원시 장안구 화산로233번길 46 1층', - contactNumber: '031-293-9294', - menus: [Array], - operatingInfos: [Array], - }, - discountContent: '', - id: 1, - isLike: false, - likeCount: 0, - name: '목구멍 율전점', - operatingEndTime: '', - operatingStartTime: '', - ratingAvg: 0, - representativeImageUrl: - 'https://search.pstatic.net/common/?autoRotate=true&type=w560_sharpen&src=https://ldb-phinf.pstatic.net/20230615_253/1686790793946ISiOc_JPEG/3%B9%F8.jpg', - representativeMenu: { - description: '시원 상큼한 하이볼3종', - imageUrl: - 'https://search.pstatic.net/common/?autoRotate=true&quality=95&type=f320_320&src=https://ldb-phinf.pstatic.net/20230525_34/16849976756701d50P_JPEG/Screenshot_20230525_095732_Samsung_Internet.jpg', - isRepresentative: true, - name: '하이볼(레몬, 자몽, 얼그레이)', - price: 7000, - }, - representativeReviewContent: null, - reviewCount: 0, - }, - { - categories: [], - detailInfo: { - address: '경기 수원시 장안구 율전로98번길 9', - contactNumber: '0507-1479-8592', - menus: [Array], - operatingInfos: [Array], - }, - discountContent: '', - id: 2, - isLike: false, - likeCount: 0, - name: '고기굽는교실 율전3반', - operatingEndTime: '', - operatingStartTime: '', - ratingAvg: 0, - representativeImageUrl: - 'https://search.pstatic.net/common/?autoRotate=true&type=w560_sharpen&src=https://ldb-phinf.pstatic.net/20230915_138/1694761539253MqBUj_JPEG/temp_file.jpg', - representativeMenu: null, - representativeReviewContent: null, - reviewCount: 0, - }, - { - categories: [], - detailInfo: { - address: '경기 수원시 장안구 율전로108번길 11 1층', - contactNumber: '0507-1460-0903', - menus: [Array], - operatingInfos: [Array], - }, - discountContent: '', - id: 3, - isLike: false, - likeCount: 0, - name: '봉수육', - operatingEndTime: '', - operatingStartTime: '', - ratingAvg: 0, - representativeImageUrl: - 'https://search.pstatic.net/common/?autoRotate=true&type=w560_sharpen&src=https://ldb-phinf.pstatic.net//20170607_114/1496834895537QbEYi_JPEG/IMG_0230.', - representativeMenu: null, - representativeReviewContent: null, - reviewCount: 0, - }, - { - categories: [], - detailInfo: { - address: '경기 수원시 장안구 율전로108번길 9 율전미주타운 1층 102호', - contactNumber: '0507-1315-4231', - menus: [Array], - operatingInfos: [Array], - }, - discountContent: '음료 한정 테이크 아웃 30% 가격 할인', - id: 4, - isLike: false, - likeCount: 0, - name: '자명문', - operatingEndTime: '', - operatingStartTime: '', - ratingAvg: 0, - representativeImageUrl: - 'https://search.pstatic.net/common/?autoRotate=true&type=w560_sharpen&src=https://ldb-phinf.pstatic.net/20201124_92/16062108769605dpF3_JPEG/xSKJpp_WcxT4xlbe8Jsq6g-O.jpeg.jpg', - representativeMenu: null, - representativeReviewContent: null, - reviewCount: 0, - }, - ]); + const [todaysPick, setTodaysPick] = useState([]); const [kingoPassData, setkingoPassData] = useState([]); @@ -177,9 +81,9 @@ export default function HomeScreen() { headers: {Authorization: `Bearer ${context.accessToken}`}, }); - console.log('response:', response.data); + console.log('response:', response.data.data.restaurants); - // setTodaysPick(response.data.data.restaurants.content); + setTodaysPick(response.data.data.restaurants); } catch (e) { console.log('error', e); } diff --git a/src/screens/list/ListMainScreen.js b/src/screens/list/ListMainScreen.js index 7226f75..7cdae01 100644 --- a/src/screens/list/ListMainScreen.js +++ b/src/screens/list/ListMainScreen.js @@ -59,7 +59,12 @@ export default function ListMainScreen() { const [sort, setSort] = useState('기본 순'); const [selectSale, setSelectSale] = useState(false); const [likedStore, setLikedStore] = useState(false); + const [search, setSearch] = useState(''); + const [myLocation, setMyLocation] = useState({ + latitude: 37.297861, + longitude: 126.971458, + }); const [pageNumber, setPageNumber] = useState(0); const catrgory = [ @@ -86,6 +91,7 @@ export default function ListMainScreen() { const getStoreDatas = async p => { try { // console.log('context.accessToken:', context.accessToken); + setPageNumber(p + 1); let discountForSkku = false; @@ -103,7 +109,6 @@ export default function ListMainScreen() { const params = { discountForSkku: discountForSkku, like: like, - sort: 'BASIC', page: pageNumber, }; @@ -188,6 +193,30 @@ export default function ListMainScreen() { break; } + switch (sort) { + case '가까운 순': + params.customSort = 'CLOSELY_DESC'; + params.latitude = myLocation.latitude; + params.longitude = myLocation.longitude; + break; + case '평점 높은 순': + params.customSort = 'RATING_DESC'; + break; + case '댓글 많은 순': + params.customSort = 'REVIEW_COUNT_DESC'; + break; + case '찜 많은 순': + params.customSort = 'LIKE_COUNT_DESC'; + break; + case '기본 순': + params.customSort = 'BASIC'; + break; + } + + if (search !== '') { + params.query = search; + } + const queryString = new URLSearchParams(params).toString(); const response = await axios.get( @@ -197,7 +226,7 @@ export default function ListMainScreen() { }, ); - console.log('response:', response.data.data.restaurants.content[0]); + // console.log('response:', response.data.data.restaurants.content[0]); if (p == 0) { setStoreDartDatas(response.data.data.restaurants.content); @@ -214,6 +243,9 @@ export default function ListMainScreen() { const onEndReached = () => { console.log('onEndReached', pageNumber); + if (pageNumber === 0) { + return; + } getStoreDatas(pageNumber); }; @@ -234,6 +266,8 @@ export default function ListMainScreen() { sort, storeScoreNaver, replyNumNaver, + myLocation, + search, ]); const listHeader = () => { @@ -255,8 +289,8 @@ export default function ListMainScreen() { justifyContent: 'center', }} onPress={() => { - //TODO: 리스트화면에도 검색 화면 추가하기 - // navigation.navigate('Search'); + setSearch(''); + navigation.navigate('Search', {setSearch: setSearch}); }}> - {'율전의 맛집은 과연 어디?'} + {search !== '' ? ( + {search} + ) : ( + + {'율전의 맛집은 과연 어디?'} + + )} @@ -709,6 +749,7 @@ export default function ListMainScreen() { '댓글 많은 순', '찜 많은 순', ]} + setLocation={setMyLocation} /> {/* 댓글수 모달 */} diff --git a/src/screens/map/MapScreen.js b/src/screens/map/MapScreen.js index ea6be20..5a65dac 100644 --- a/src/screens/map/MapScreen.js +++ b/src/screens/map/MapScreen.js @@ -73,6 +73,7 @@ export default function MapScreen() { const [selectSale, setSelectSale] = useState(false); const [likedStore, setLikedStore] = useState(false); + const [search, setSearch] = useState(''); const closeStoreModalVisible = () => { setStoreModalVisible(false); @@ -224,6 +225,10 @@ export default function MapScreen() { break; } + if (search !== '') { + params.query = search; + } + const queryString = new URLSearchParams(params).toString(); const response = await axios.get( @@ -256,6 +261,7 @@ export default function MapScreen() { likedStore, storeScoreNaver, replyNumNaver, + search, ]); return ( @@ -306,7 +312,8 @@ export default function MapScreen() { justifyContent: 'center', }} onPress={() => { - navigation.navigate('Search'); + setSearch(''); + navigation.navigate('Search', {setSearch: setSearch}); }}> - {'율전의 맛집은 과연 어디?'} + {search !== '' ? ( + {search} + ) : ( + + {'율전의 맛집은 과연 어디?'} + + )} diff --git a/src/screens/map/SearchScreen.js b/src/screens/map/SearchScreen.js deleted file mode 100644 index 92b6f72..0000000 --- a/src/screens/map/SearchScreen.js +++ /dev/null @@ -1,119 +0,0 @@ -/* eslint-disable react/self-closing-comp */ -/* eslint-disable react-native/no-inline-styles */ -import React, {useState, useCallback, useEffect} from 'react'; -import { - View, - Text, - SafeAreaView, - ScrollView, - StyleSheet, - Switch, -} from 'react-native'; -import { - COLOR_WHITE, - COLOR_BACKGROUND, - COLOR_GRAY, - COLOR_PRIMARY, - COLOR_TEXT_BLACK, - COLOR_TEXT70GRAY, - COLOR_TEXT60GRAY, -} from '../../assets/color'; -import AnimatedButton from '../../components/AnimationButton'; -import Header from '../../components/Header'; -import {useNavigation} from '@react-navigation/native'; -import MapView, {PROVIDER_GOOGLE, Marker} from 'react-native-maps'; -import {BlurView} from '@react-native-community/blur'; -import {SvgXml} from 'react-native-svg'; -import {svgXml} from '../../assets/svg'; -import MapDart from '../../components/MapDart'; -import Modal from 'react-native-modal'; -import {Dimensions} from 'react-native'; -import {TextInput} from 'react-native-gesture-handler'; -import StoreCompo from '../../components/StoreCompo'; - -const windowWidth = Dimensions.get('window').width; - -export default function SearchScreen() { - const navigation = useNavigation(); - - const [searchText, setSearchText] = useState(''); - - //TODO: 검색어를 받아와서 검색하는 함수 - function searchStore(inputString) { - console.log('검색어:', inputString); - } - - return ( - <> -
- - - {/* 검색창 */} - - - { - searchStore(searchText); - }} - style={{ - padding: 8, - }}> - - - {}} - placeholder={'율전의 맛집은 과연 어디?'} - placeholderTextColor={'#888888'} - style={styles.textInput} - onChangeText={text => { - setSearchText(text); - }} - blurOnSubmit={false} - maxLength={200} - value={searchText} - onSubmitEditing={() => { - console.log('검색 제출'); - searchStore(searchText); - }} - // multiline={true} - textAlignVertical="center" - autoCapitalize="none" - autoComplete="off" - autoCorrect={false} - numberOfLines={1} - /> - - - - - - ); -} - -const styles = StyleSheet.create({ - entire: { - flex: 1, - backgroundColor: COLOR_BACKGROUND, - alignItems: 'center', - }, - textInput: { - marginLeft: 10, - flex: 1, - fontSize: 12, - color: COLOR_TEXT_BLACK, - padding: 0, - }, -}); diff --git a/src/screens/signup/ProfileSetScreen.js b/src/screens/signup/ProfileSetScreen.js index a7cf513..15c547b 100644 --- a/src/screens/signup/ProfileSetScreen.js +++ b/src/screens/signup/ProfileSetScreen.js @@ -58,7 +58,7 @@ export default function ProfileSetScreen(props) { //회원가입 하고 토큰 저장하는 부분 const response = await axios.post(`${API_URL}/v1/users/email/sign-up`, { email: signUpData.email, - nickname: signUpData.name, + nickname: signUpData.nickname, password: signUpData.password, profileImageUrl: profileImage, });