|
@@ -8,8 +8,7 @@
|
|
import { FontAwesome } from "@expo/vector-icons";
|
|
import { FontAwesome } from "@expo/vector-icons";
|
|
import { useNavigationState } from "@react-navigation/native";
|
|
import { useNavigationState } from "@react-navigation/native";
|
|
import React, { MutableRefObject, useEffect, useRef, useState } from "react";
|
|
import React, { MutableRefObject, useEffect, useRef, useState } from "react";
|
|
-import { FlatList, Dimensions, Image, ScrollView, StyleSheet, Text, TextInput, View } from "react-native";
|
|
|
|
-import { TouchableOpacity } from "react-native-gesture-handler";
|
|
|
|
|
|
+import { FlatList, Dimensions, Image, ScrollView, StyleSheet, Text, TextInput, View, TouchableOpacity } from "react-native";
|
|
import Picker from "react-native-picker-select";
|
|
import Picker from "react-native-picker-select";
|
|
import { QueryStatus } from "react-query";
|
|
import { QueryStatus } from "react-query";
|
|
import { LMComment } from "../../../../data/comments";
|
|
import { LMComment } from "../../../../data/comments";
|
|
@@ -17,7 +16,7 @@ import { Landmark, LMPhoto } from "../../../../data/landmarks";
|
|
import MapView, {Marker} from "react-native-maps";
|
|
import MapView, {Marker} from "react-native-maps";
|
|
import { usePermissions } from "../../../../data/PermissionsContext";
|
|
import { usePermissions } from "../../../../data/PermissionsContext";
|
|
import { MainTabsNavigationProp } from "../../../../navigation/MainTabsNavigator";
|
|
import { MainTabsNavigationProp } from "../../../../navigation/MainTabsNavigator";
|
|
-import { lmTypes as allLmTypes, lmTypesIndoor, catTypes } from "../../../../utils/GlobalUtils";
|
|
|
|
|
|
+import { lmTypes as allLmTypes, lmTypesIndoor, catTypes, catTypesInGroup } from "../../../../utils/GlobalUtils";
|
|
import LandmarkTypePicker from "../../../LandmarkTypePicker";
|
|
import LandmarkTypePicker from "../../../LandmarkTypePicker";
|
|
import { Separator } from "../../../Separator";
|
|
import { Separator } from "../../../Separator";
|
|
import { CommentsContainer } from "./CommentsContainer";
|
|
import { CommentsContainer } from "./CommentsContainer";
|
|
@@ -26,6 +25,7 @@ import { useOutdoorMapState } from "../../MainMapComponent/useMapState";
|
|
import { TagContainer } from "./TagContainer";
|
|
import { TagContainer } from "./TagContainer";
|
|
import CheckBox from "@react-native-community/checkbox";
|
|
import CheckBox from "@react-native-community/checkbox";
|
|
import DatePicker from "react-native-date-picker";
|
|
import DatePicker from "react-native-date-picker";
|
|
|
|
+import { useAuth } from "../../../../data/Auth/AuthContext";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -62,6 +62,11 @@ interface DetailsBodyProps {
|
|
uri: String
|
|
uri: String
|
|
tagLandmark: (tagType: string) => void
|
|
tagLandmark: (tagType: string) => void
|
|
taggedByUser?: Array<boolean>
|
|
taggedByUser?: Array<boolean>
|
|
|
|
+ applyFilters: (landmarks?: Landmark[], getGroupList?: boolean, parent?: string) => Landmark[]
|
|
|
|
+ landmarks: Landmark[]
|
|
|
|
+ toggleDetailsPanel: (state: boolean) => void,
|
|
|
|
+ setLandmark: (landmark: string) => void;
|
|
|
|
+ promptAddLandmark: (longitude: number, latitude: number, floor?: number, lmCount?: string, parent?: string) => void
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -70,6 +75,7 @@ interface DetailsBodyProps {
|
|
export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
|
|
export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
|
|
const {locationPermissionsGranted, checkLocationPermissions, voicePermissionsGranted, checkVoicePermissions} = usePermissions();
|
|
const {locationPermissionsGranted, checkLocationPermissions, voicePermissionsGranted, checkVoicePermissions} = usePermissions();
|
|
const mapState = useOutdoorMapState()
|
|
const mapState = useOutdoorMapState()
|
|
|
|
+ const {landmarkOwnedByUser} = useAuth()
|
|
|
|
|
|
const navigationState = useNavigationState(state => state)
|
|
const navigationState = useNavigationState(state => state)
|
|
const [currentRoute, setCurrentRoute] = useState<string>()
|
|
const [currentRoute, setCurrentRoute] = useState<string>()
|
|
@@ -108,6 +114,7 @@ export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
|
|
|
|
|
|
const [date, setDate] = useState(new Date())
|
|
const [date, setDate] = useState(new Date())
|
|
const [showExpire, toggleShowExpire] = useState<boolean>(false)
|
|
const [showExpire, toggleShowExpire] = useState<boolean>(false)
|
|
|
|
+ const [groupList, toggleGroupList] = useState<boolean>(props.landmark?.landmark_type == 30 ? true : false)
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
if (props.editingEnabled && !showExpire)
|
|
if (props.editingEnabled && !showExpire)
|
|
@@ -115,7 +122,7 @@ export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
|
|
else if (props.editingEnabled && showExpire)
|
|
else if (props.editingEnabled && showExpire)
|
|
props.setUpdatedLandmark({...props.updatedLandmark, expiry_date: date})
|
|
props.setUpdatedLandmark({...props.updatedLandmark, expiry_date: date})
|
|
}, [showExpire])
|
|
}, [showExpire])
|
|
-
|
|
|
|
|
|
+
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
if (showExpire)
|
|
if (showExpire)
|
|
props.setUpdatedLandmark({...props.updatedLandmark, expiry_date: date})
|
|
props.setUpdatedLandmark({...props.updatedLandmark, expiry_date: date})
|
|
@@ -132,20 +139,27 @@ export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
|
|
return(
|
|
return(
|
|
<>
|
|
<>
|
|
<LandmarkTypePicker
|
|
<LandmarkTypePicker
|
|
- placeholder={{}}
|
|
|
|
- value={props.updatedLandmark?.landmark_type}
|
|
|
|
|
|
+ placeholder={{ label: "Select a landmark type...", value: 0 }}
|
|
|
|
+ value={props.updatedLandmark?.landmark_type}
|
|
onValueChange={(value) => {
|
|
onValueChange={(value) => {
|
|
- props.setUpdatedLandmark({...props.updatedLandmark, landmark_type: value, title: lmTypes[value].label})
|
|
|
|
- }}
|
|
|
|
- cats={Object.keys(lmTypes)?.filter(icon => parseInt(icon) != props.landmark?.landmark_type).map(icon => {
|
|
|
|
|
|
+ if (value) {
|
|
|
|
+ props.setUpdatedLandmark({ ...props.updatedLandmark, landmark_type: value, title: lmTypes[value].label })
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ props.setUpdatedLandmark({ ...props.updatedLandmark, landmark_type: undefined, title: 'no title' })
|
|
|
|
+ }
|
|
|
|
+ }}
|
|
|
|
+ cats={Object.keys(props.landmark?.groupCount == -1 ? catTypesInGroup : catTypes)?.map(icon => {
|
|
return (
|
|
return (
|
|
- {label: catTypes[parseInt(icon)]?.cat.toUpperCase(), value: icon, key: icon}
|
|
|
|
- )})}
|
|
|
|
- items={Object.keys(lmTypes)?.filter(icon => parseInt(icon) != props.landmark?.landmark_type).map(icon => {
|
|
|
|
|
|
+ { label: catTypes[parseInt(icon)]?.cat.toUpperCase(), value: icon, key: icon }
|
|
|
|
+ )
|
|
|
|
+ })}
|
|
|
|
+ items={Object.keys(lmTypes)?.map(icon => {
|
|
return (
|
|
return (
|
|
- {label: lmTypes[parseInt(icon)].label.toUpperCase(), value: icon,
|
|
|
|
- key: lmTypes[parseInt(icon)].cat.toUpperCase()}
|
|
|
|
- )})}/>
|
|
|
|
|
|
+ { label: lmTypes[parseInt(icon)]?.label.toUpperCase(),
|
|
|
|
+ value: icon, key: lmTypes[parseInt(icon)]?.cat.toUpperCase() }
|
|
|
|
+ )
|
|
|
|
+ })}/>
|
|
</>
|
|
</>
|
|
)
|
|
)
|
|
}
|
|
}
|
|
@@ -176,9 +190,16 @@ export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
|
|
* @param
|
|
* @param
|
|
*/
|
|
*/
|
|
const EditingDisabledUpperView: React.FC = () => {
|
|
const EditingDisabledUpperView: React.FC = () => {
|
|
|
|
+ if (!groupList) {
|
|
return (
|
|
return (
|
|
<View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
|
|
<View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
|
|
<View style={{flex: 8, flexDirection: 'column', marginBottom: 20}}>
|
|
<View style={{flex: 8, flexDirection: 'column', marginBottom: 20}}>
|
|
|
|
+ {props.landmark?.groupCount == -1 ?
|
|
|
|
+ <TouchableOpacity style={styles.groupReturnButton} onPress={() => {props.setLandmark(props.landmark?.parent); toggleGroupList(true)}}>
|
|
|
|
+ <FontAwesome size={15} color="white" name="chevron-left"/>
|
|
|
|
+ <Text style={{color: "white", marginLeft: 5}}>Return to group</Text>
|
|
|
|
+ </TouchableOpacity>
|
|
|
|
+ : null}
|
|
<Text style={{color: 'white', marginBottom: 10, fontSize: 15}}>{lmTypes[props.landmark?.landmark_type]?.label.toUpperCase()}</Text>
|
|
<Text style={{color: 'white', marginBottom: 10, fontSize: 15}}>{lmTypes[props.landmark?.landmark_type]?.label.toUpperCase()}</Text>
|
|
<ScrollView nestedScrollEnabled={true}>
|
|
<ScrollView nestedScrollEnabled={true}>
|
|
<Text style={{color: 'white', fontSize: 13}}>{props.landmark?.description}</Text>
|
|
<Text style={{color: 'white', fontSize: 13}}>{props.landmark?.description}</Text>
|
|
@@ -188,6 +209,44 @@ export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
|
|
</View>
|
|
</View>
|
|
{props.landmark?.landmark_type ? <Image source={lmTypes[props.landmark?.landmark_type]?.image} /> : null}
|
|
{props.landmark?.landmark_type ? <Image source={lmTypes[props.landmark?.landmark_type]?.image} /> : null}
|
|
</View>
|
|
</View>
|
|
|
|
+ )
|
|
|
|
+ } else return null
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Sub-component that renders the list of landmarks in a group
|
|
|
|
+ */
|
|
|
|
+ const LandmarkGroupListView: React.FC = () => {
|
|
|
|
+ return (
|
|
|
|
+ <View>
|
|
|
|
+ <Text style={{color: 'white', fontSize: 13}}>{props.landmark?.description}</Text>
|
|
|
|
+ {props.landmark?.expiry_date ?
|
|
|
|
+ <Text style={{color: 'white', fontSize: 13}}>Landmark group expires on {props.landmark.expiry_date.toString().substring(0,10)}</Text> : null}
|
|
|
|
+ <Text style={{fontSize: 16, color: "white", marginBottom: 10, marginTop: 5}}>Landmarks in this group:</Text>
|
|
|
|
+ <ScrollView>
|
|
|
|
+ {props.applyFilters(props.landmarks, true, props.landmark?.id)?.map((landmark) => {
|
|
|
|
+ return (
|
|
|
|
+ <TouchableOpacity key={landmark.id} style={styles.groupListItem}
|
|
|
|
+ onPress={() => {
|
|
|
|
+ // props.toggleDetailsPanel(false)
|
|
|
|
+ console.log('changing to landmark' + lmTypes[landmark?.landmark_type]?.label)
|
|
|
|
+ toggleGroupList(false)
|
|
|
|
+ props.setLandmark(landmark.id)
|
|
|
|
+ }}>
|
|
|
|
+ <Image style={{ height: 52.5, width: 37.5, zIndex: 10, margin: 5 }} source={lmTypes[landmark.landmark_type]?.image} />
|
|
|
|
+ <Text style={{marginLeft: 10}}>{lmTypes[landmark?.landmark_type]?.label.toUpperCase()}</Text>
|
|
|
|
+ </TouchableOpacity>
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ )}
|
|
|
|
+ {landmarkOwnedByUser(props.landmark) ?
|
|
|
|
+ <TouchableOpacity style={{marginTop: 30, justifyContent: 'center', alignItems: 'center', opacity: .7}}
|
|
|
|
+ onPress={() => {props.promptAddLandmark(props.landmark?.longitude, props.landmark?.latitude, undefined, "groupItem", props.landmark?.id)}}>
|
|
|
|
+ <Text style={{fontSize: 20, marginBottom: 10, color: 'white'}}>Add landmark to group</Text>
|
|
|
|
+ <FontAwesome name="plus" size={30} color='white' />
|
|
|
|
+ </TouchableOpacity> : null }
|
|
|
|
+ </ScrollView>
|
|
|
|
+ </View>
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
|
|
@@ -195,25 +254,24 @@ export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
|
|
<ScrollView ref={mainScrollRef} nestedScrollEnabled={true} contentContainerStyle={{justifyContent: 'space-between'}} style={{flex: 1, marginHorizontal: 20}}>
|
|
<ScrollView ref={mainScrollRef} nestedScrollEnabled={true} contentContainerStyle={{justifyContent: 'space-between'}} style={{flex: 1, marginHorizontal: 20}}>
|
|
{props.editingEnabled ?
|
|
{props.editingEnabled ?
|
|
<>
|
|
<>
|
|
- <Text onPress={() => toggleEditLocation(!editLocation)} style={{color: 'white', marginBottom: 10}}>Tap to edit location</Text>
|
|
|
|
- {editLocation && <MapView
|
|
|
|
|
|
+ {props.landmark?.groupCount !== -1 && // Prevent users from editing the location of landmarks in a group (must edit group itself)
|
|
|
|
+ <MapView
|
|
toolbarEnabled={false}
|
|
toolbarEnabled={false}
|
|
onPress={(e) =>
|
|
onPress={(e) =>
|
|
props.setUpdatedLandmark({...props.updatedLandmark, longitude: e.nativeEvent.coordinate.longitude, latitude: e.nativeEvent.coordinate.latitude})
|
|
props.setUpdatedLandmark({...props.updatedLandmark, longitude: e.nativeEvent.coordinate.longitude, latitude: e.nativeEvent.coordinate.latitude})
|
|
}
|
|
}
|
|
testID="mapViewLocationEdit"
|
|
testID="mapViewLocationEdit"
|
|
- style={{ width: '100%', height: Dimensions.get("window").height * .4, marginBottom: 20}}
|
|
|
|
|
|
+ style={{ width: '100%', height: Dimensions.get("window").height * .4, marginBottom: 20, marginTop: 10}}
|
|
initialRegion={{latitude: props.landmark?.latitude, longitude: props.landmark?.longitude, latitudeDelta: 0.01, longitudeDelta: 0.01}}
|
|
initialRegion={{latitude: props.landmark?.latitude, longitude: props.landmark?.longitude, latitudeDelta: 0.01, longitudeDelta: 0.01}}
|
|
showsUserLocation={locationPermissionsGranted}
|
|
showsUserLocation={locationPermissionsGranted}
|
|
showsMyLocationButton={false}
|
|
showsMyLocationButton={false}
|
|
>
|
|
>
|
|
-
|
|
|
|
<Marker
|
|
<Marker
|
|
coordinate={{ latitude: props.updatedLandmark?.latitude as number, longitude: props.updatedLandmark?.longitude as number }} >
|
|
coordinate={{ latitude: props.updatedLandmark?.latitude as number, longitude: props.updatedLandmark?.longitude as number }} >
|
|
{props.updatedLandmark?.landmark_type ? <Image style={{ height: 35, width: 25 }} source={lmTypes[props.updatedLandmark?.landmark_type]?.image} /> : null}
|
|
{props.updatedLandmark?.landmark_type ? <Image style={{ height: 35, width: 25 }} source={lmTypes[props.updatedLandmark?.landmark_type]?.image} /> : null}
|
|
</Marker>
|
|
</Marker>
|
|
</MapView>}
|
|
</MapView>}
|
|
- <LandmarkTypePickerContainer />
|
|
|
|
|
|
+ {props.landmark?.landmark_type !== 30 && <LandmarkTypePickerContainer /> /* Prevent editing of landmark type if it is a group */}
|
|
<Separator style={{marginVertical: 10, opacity: .5}} color="lightgray" />
|
|
<Separator style={{marginVertical: 10, opacity: .5}} color="lightgray" />
|
|
<Text style={{color: 'white', marginBottom: 10}}>Description</Text>
|
|
<Text style={{color: 'white', marginBottom: 10}}>Description</Text>
|
|
<ScrollView nestedScrollEnabled={true} style={{backgroundColor: 'white', marginBottom: 20}}>
|
|
<ScrollView nestedScrollEnabled={true} style={{backgroundColor: 'white', marginBottom: 20}}>
|
|
@@ -245,14 +303,16 @@ export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
|
|
fadeToColor="none" />}
|
|
fadeToColor="none" />}
|
|
</View>
|
|
</View>
|
|
</>: <EditingDisabledUpperView />}
|
|
</>: <EditingDisabledUpperView />}
|
|
- {!props.editingEnabled ?
|
|
|
|
|
|
+ {!props.editingEnabled && groupList ?
|
|
|
|
+ <LandmarkGroupListView /> : null}
|
|
|
|
+ {!props.editingEnabled && !groupList ?
|
|
<TagContainer
|
|
<TagContainer
|
|
landmark={props.landmark}
|
|
landmark={props.landmark}
|
|
tagLandmark={props.tagLandmark}
|
|
tagLandmark={props.tagLandmark}
|
|
toggleLmDetails={props.toggleLmDetails}
|
|
toggleLmDetails={props.toggleLmDetails}
|
|
authNavigation={props.authNavigation}
|
|
authNavigation={props.authNavigation}
|
|
taggedByUser={props.taggedByUser} /> : null}
|
|
taggedByUser={props.taggedByUser} /> : null}
|
|
- {!props.editingEnabled ?
|
|
|
|
|
|
+ {!props.editingEnabled && !groupList ?
|
|
<CommentsContainer
|
|
<CommentsContainer
|
|
toggleLmDetails={props.toggleLmDetails}
|
|
toggleLmDetails={props.toggleLmDetails}
|
|
authNavigation={props.authNavigation}
|
|
authNavigation={props.authNavigation}
|
|
@@ -273,7 +333,7 @@ export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
|
|
startEditingComment={props.startEditingComment}
|
|
startEditingComment={props.startEditingComment}
|
|
deleteComment={props.deleteComment}
|
|
deleteComment={props.deleteComment}
|
|
uri={props.uri} /> : null}
|
|
uri={props.uri} /> : null}
|
|
- {!props.editingEnabled && !props.keyboardOpened ?
|
|
|
|
|
|
+ {!props.editingEnabled && !props.keyboardOpened && !groupList ?
|
|
<LandmarkPhotos
|
|
<LandmarkPhotos
|
|
profileId={props.profileId}
|
|
profileId={props.profileId}
|
|
deletePhotoStatus={props.deletePhotoStatus}
|
|
deletePhotoStatus={props.deletePhotoStatus}
|
|
@@ -303,4 +363,29 @@ const styles = StyleSheet.create({
|
|
flex: 5,
|
|
flex: 5,
|
|
marginBottom: 40,
|
|
marginBottom: 40,
|
|
},
|
|
},
|
|
|
|
+ groupListItem: {
|
|
|
|
+ flex: 1,
|
|
|
|
+ flexDirection: "row",
|
|
|
|
+ alignItems: "center",
|
|
|
|
+ borderColor: "white",
|
|
|
|
+ borderWidth: 1,
|
|
|
|
+ borderRadius: 10,
|
|
|
|
+ backgroundColor: "white",
|
|
|
|
+ margin: 10,
|
|
|
|
+ },
|
|
|
|
+ groupReturnButton: {
|
|
|
|
+ flex: 1,
|
|
|
|
+ flexDirection: "row",
|
|
|
|
+ alignItems: "center",
|
|
|
|
+ marginBottom: 5,
|
|
|
|
+ paddingTop: 5,
|
|
|
|
+ paddingBottom: 5,
|
|
|
|
+ },
|
|
|
|
+ toggleLocationEditor: {
|
|
|
|
+ flex: 1,
|
|
|
|
+ flexDirection: "row",
|
|
|
|
+ alignItems: "center",
|
|
|
|
+ marginTop: 5,
|
|
|
|
+ marginBottom: 5,
|
|
|
|
+ }
|
|
})
|
|
})
|