diff --git a/app/src/assets/images/CancelSvg.tsx b/app/src/assets/images/CancelSvg.tsx index 9e4f350..9b6dd4e 100644 --- a/app/src/assets/images/CancelSvg.tsx +++ b/app/src/assets/images/CancelSvg.tsx @@ -3,7 +3,7 @@ import Svg, {Path} from 'react-native-svg'; export default function CancelSvg({width, height, fill}: SvgProps) { return ( - + ); } diff --git a/app/src/assets/images/reportNewBin/AddressSvg.tsx b/app/src/assets/images/reportNewBin/AddressSvg.tsx deleted file mode 100644 index 38d5028..0000000 --- a/app/src/assets/images/reportNewBin/AddressSvg.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import Svg, {Path} from 'react-native-svg'; -export default function AddressSvg({width, height, fill}: SvgProps) { - return ( - - - - ); -} diff --git a/app/src/components/ReportNewBinNavigator.tsx b/app/src/components/ReportNewBinNavigator.tsx index 0ae97d8..68844ae 100644 --- a/app/src/components/ReportNewBinNavigator.tsx +++ b/app/src/components/ReportNewBinNavigator.tsx @@ -1,5 +1,6 @@ import { createNativeStackNavigator } from "@react-navigation/native-stack"; import ReportNewBin from "screens/reportNewBin/ReportNewBin"; +import ReportNewBinDetail from "screens/reportNewBinDetail/ReportNewBinDetail"; export default function ReportNewBinNavigator() { const Stack = createNativeStackNavigator(); @@ -7,6 +8,7 @@ export default function ReportNewBinNavigator() { return ( + ); } \ No newline at end of file diff --git a/app/src/screens/reportNewBin/ReportNewBin.tsx b/app/src/screens/reportNewBin/ReportNewBin.tsx index 4e18535..e91cafb 100644 --- a/app/src/screens/reportNewBin/ReportNewBin.tsx +++ b/app/src/screens/reportNewBin/ReportNewBin.tsx @@ -6,7 +6,9 @@ import Animated, {useAnimatedStyle, withTiming} from 'react-native-reanimated'; import WebView, { WebViewMessageEvent } from 'react-native-webview'; import {mapStore} from 'store/Store'; import * as S from 'screens/reportNewBin/ReportNewBin.style'; -import AddressSvg from 'assets/images/reportNewBin/AddressSvg'; +import { NavigationProp, useNavigation } from '@react-navigation/native'; +import LocationSvg from 'assets/images/LocationSvg'; +import { Palette } from 'constants/palette'; export default function ReportNewBin() { const webViewRef = useRef(null); @@ -16,8 +18,10 @@ export default function ReportNewBin() { // const URL = 'https://binvoyage.netlify.app/reportNewBin'; const URL = 'https://feature-38--binvoyage.netlify.app/reportNewBin'; const alertShown = useRef(false); + const navigation = useNavigation>(); + const [markerPosition, setMarkerPosition] = useState<[number, number] | null>(null); + const [address, setAddress] = useState('서울 성북구 삼선교로 16길 16-3'); - const {width, height} = Dimensions.get('window'); const refreshWrapperBottom = bottomSheetOffset > 0 ? bottomSheetOffset + 10 : 40; const animatedStyle = useAnimatedStyle(() => { @@ -117,6 +121,7 @@ export default function ReportNewBin() { const data = JSON.parse(e.nativeEvent.data); if (data.type === 'newBinPoint') { console.log("newBinPoint:", data.payload.latitude, data.payload.longitude); + setMarkerPosition([data.payload.latitude, data.payload.longitude]); } } catch (err) { console.log(err); @@ -141,13 +146,19 @@ export default function ReportNewBin() { - + - - 서울 성북구 삼선교로 16길 16-3 + + {address} - + + navigation.navigate('ReportNewBinDetail', { + address, + coordinate: markerPosition, + }) + }> There’s a bin here! diff --git a/app/src/screens/reportNewBinDetail/ReportNewBinDetail.style.ts b/app/src/screens/reportNewBinDetail/ReportNewBinDetail.style.ts new file mode 100644 index 0000000..79dda58 --- /dev/null +++ b/app/src/screens/reportNewBinDetail/ReportNewBinDetail.style.ts @@ -0,0 +1,133 @@ +import DefaultText from 'components/DefaultText'; +import {Palette} from 'constants/palette'; +import {Typo} from 'constants/typo'; +import {Dimensions} from 'react-native'; +import styled from 'styled-components/native'; + +const screenWidth = Dimensions.get('window').width; +const width = screenWidth - 32; + +export const Container = styled.View` + flex: 1; + background: ${Palette.White}; + padding: 10px 16px 0px; +`; + +export const ArrowPrevWrapper = styled.TouchableOpacity` + width: 24px; + height: 24px; + justify-content: center; + align-items: center; + margin-bottom: 16px; +`; + +export const LocationWrapper = styled.View` + flex-direction: row; + align-items: center; + gap: 3px; + padding: 10px 12px; + background: ${Palette.Gray1}; + border-radius: 10px; + shadow-color: rgba(0, 0, 0, 0.2); + shadow-offset: 0px 2px; + shadow-opacity: 1; + shadow-radius: 6px; + elevation: 3; +`; + +export const LocationText = styled(DefaultText)` + font-size: ${Typo.B3.fontSize}; + font-weight: ${Typo.B3.fontWeight}; + color: #3b3f4a; + flex-shrink: 1; + flex-wrap: wrap; +`; + +export const Title = styled(DefaultText)` + font-size: ${Typo.Title1.fontSize}; + font-weight: ${Typo.Title1.fontWeight}; + color: ${Palette.Black}; + margin-top: 22px; + margin-bottom: 26px; +`; + +export const SubTitle = styled(DefaultText)` + font-size: ${Typo.SubTitle.fontSize}; + font-weight: ${Typo.SubTitle.fontWeight}; + color: ${Palette.Black}; + margin-bottom: 12px; +`; + +export const SelectWrapper = styled.View` + flex-direction: row; + row-gap: 12px; + column-gap: 16px; + flex-wrap: wrap; +`; + +export const SelectItem = styled.TouchableOpacity<{isSelected: boolean}>` + padding: 10px 22px; + border-radius: 22px; + flex-shrink: 0; + background: ${props => props.isSelected ? Palette.Primary : Palette.Gray2}; + +`; + +export const TextSelectItem = styled(DefaultText)<{isSelected: boolean}>` + font-size: ${Typo.B3.fontSize}; + font-weight: ${Typo.B3.fontWeight}; + color: ${props => props.isSelected ? Palette.White : Palette.Gray4}; + text-align: center; +` + +export const ReviewInput = styled.TextInput` + width: 100%; + height: 150px; + border-radius: 8px; + padding: 12px 14px; + background: ${Palette.Gray1}; + font-size: ${Typo.B3.fontSize}; + font-weight: ${Typo.B3.fontWeight}; + line-height: 19px; + color: ${Palette.Black}; + margin: 18px 0px 15px; +`; + +export const AddPicture = styled.TouchableOpacity` + width: 100%; + height: 134px; + justify-content: center; + background: ${Palette.P100}; + border-radius: 8px; + padding: 22px 15px; +`; + +export const IconAddPicture = styled.ImageBackground` + width: 35px; + height: 35px; + align-self: center; + margin-bottom: 10px; +` + +export const TextB3 = styled(DefaultText)` + font-size: ${Typo.B3.fontSize}; + font-weight: ${Typo.B3.fontWeight}; + color: ${Palette.Gray6}; + text-align: center; +`; + +export const Button = styled.TouchableOpacity<{isValid: boolean}>` + width: 100%; + padding: 16px 30px; + justify-content: center; + align-items: center; + background: ${props => props.isValid ? Palette.Primary : Palette.Gray3}; + border-radius: 10px; + margin-bottom: 20px; +`; + +export const ButtonText = styled(DefaultText)<{isValid: boolean}>` + font-size: ${Typo.Button1.fontSize}; + font-weight: ${Typo.Button1.fontWeight}; + color: ${props => props.isValid ? Palette.White : Palette.Gray5}; +`; \ No newline at end of file diff --git a/app/src/screens/reportNewBinDetail/ReportNewBinDetail.tsx b/app/src/screens/reportNewBinDetail/ReportNewBinDetail.tsx new file mode 100644 index 0000000..f4c82aa --- /dev/null +++ b/app/src/screens/reportNewBinDetail/ReportNewBinDetail.tsx @@ -0,0 +1,122 @@ +import {NavigationProp, RouteProp, useNavigation} from '@react-navigation/native'; +import api from 'api/api'; +import CancelSvg from 'assets/images/CancelSvg'; +import LocationSvg from 'assets/images/LocationSvg'; +import {Palette} from 'constants/palette'; +import {useEffect, useState} from 'react'; +import {ScrollView} from 'react-native'; +import Toast from 'react-native-toast-message'; +import * as S from 'screens/reportNewBinDetail/ReportNewBinDetail.style'; + +type ReportNewBinProps = { + route: RouteProp; +} + +export default function ReportNewBinDetail({route}: ReportNewBinProps) { + const {address, coordinate} = route.params; + const navigation = useNavigation>(); + const navigation2 = useNavigation>(); + const binTypeLabel = ['Trash', 'Recycling']; + const locationDetailLabel = ['Subway Entrance', 'Bus/Taxi Stop', 'Roadside', 'Square/Park', 'Other']; + const [selectedBinTypeLabel, setSelectedBinTypeLabel] = useState(-1); + const [selectedLocationDetailLabel, setSelectedLocationDetailLabel] = useState(-1); + const placeholder = `In front of a store (e.g. Olive Young) or by the bus stop? More details will help fellow wanderers!`; + const [content, setContent] = useState(''); + const [isValid, setIsValid] = useState(false); + + const handleSubmit = async () => { + try { + const response = await api.post(`/bin/new`, { + address: address, + lat: coordinate![0], + lng: coordinate![1], + detail: content, + type_no: selectedBinTypeLabel === 0 ? 1 : 2, + location_type_no: selectedLocationDetailLabel + 1, + image: 'https://test.test/123', + }); + if (response.data.success) { + Toast.show({ + type: 'success', + text1: 'Thank you for letting us know!', + position: 'bottom', + bottomOffset: 100, + visibilityTime: 2000, + }); + navigation2.navigate('Home'); + } else { + Toast.show({ + type: 'error', + text1: 'Failed to submit. Please try again later.', + position: 'bottom', + bottomOffset: 100, + visibilityTime: 2000, + }); + } + } catch (error: any) { + console.log(error); + Toast.show({ + type: 'error', + text1: 'Failed to submit. Please try again later.', + position: 'bottom', + bottomOffset: 100, + visibilityTime: 2000, + }); + } + } + + useEffect(() => { + if (selectedBinTypeLabel !== -1 && selectedLocationDetailLabel !== -1) { + setIsValid(true); + return; + } + setIsValid(false); + }, [selectedBinTypeLabel, selectedLocationDetailLabel]) + + return ( + + navigation.goBack()}> + + + + + + {address} + + {`Tell us more about the bin\nyou found`} + Bin type + + {binTypeLabel.map((item, index) => ( + setSelectedBinTypeLabel(index)}> + {item} + + ))} + + Location details + + {locationDetailLabel.map((item, index) => ( + setSelectedLocationDetailLabel(index)}> + {item} + + ))} + + + + + Upload a photo of the bin (Optional) + You can upload only one photo! + + + + Submit + + + ); +} diff --git a/app/src/types/navigator.d.ts b/app/src/types/navigator.d.ts index a599823..4598c59 100644 --- a/app/src/types/navigator.d.ts +++ b/app/src/types/navigator.d.ts @@ -58,6 +58,10 @@ type RootBinDetailParamList = { type RootReportNewBinParamList = { ReportNewBin: undefined; + ReportNewBinDetail: { + address: string; + coordinate: [number, number] | null; // [lat, lng] + }; } type RootMyParamList = {