Skip to content

Commit eb48581

Browse files
authored
Merge pull request #378 from wavect/wsdt/map
feat: new map view start
2 parents 2e4ddf3 + a17749d commit eb48581

File tree

8 files changed

+302
-87
lines changed

8 files changed

+302
-87
lines changed

mobile/components/OCard/OCard.tsx

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import MaterialIcons from "@expo/vector-icons/MaterialIcons";
2+
import React, { useState } from "react";
3+
import {
4+
Animated,
5+
StyleSheet,
6+
TouchableOpacity,
7+
ViewStyle,
8+
} from "react-native";
9+
10+
interface IOCardProps {
11+
children: React.ReactNode;
12+
style?: ViewStyle;
13+
onDismiss?: () => void;
14+
dismissable?: boolean;
15+
initiallyVisible?: boolean;
16+
}
17+
18+
const OCard = ({
19+
children,
20+
style,
21+
onDismiss,
22+
dismissable = false,
23+
initiallyVisible = true,
24+
}: IOCardProps) => {
25+
const [visible, setVisible] = useState(initiallyVisible);
26+
const fadeAnim = useState(new Animated.Value(1))[0];
27+
28+
const handleDismiss = () => {
29+
Animated.timing(fadeAnim, {
30+
toValue: 0,
31+
duration: 300,
32+
useNativeDriver: true,
33+
}).start(() => {
34+
setVisible(false);
35+
onDismiss?.();
36+
});
37+
};
38+
39+
if (!visible) {
40+
return null;
41+
}
42+
43+
return (
44+
<Animated.View
45+
style={[
46+
styles.card,
47+
style,
48+
{ opacity: fadeAnim },
49+
dismissable ? { paddingRight: 30 } : undefined,
50+
]}
51+
>
52+
{dismissable && (
53+
<TouchableOpacity
54+
style={styles.closeButton}
55+
onPress={handleDismiss}
56+
hitSlop={{ top: 10, right: 10, bottom: 10, left: 10 }}
57+
>
58+
<MaterialIcons name="close" size={20} color="#666" />
59+
</TouchableOpacity>
60+
)}
61+
{children}
62+
</Animated.View>
63+
);
64+
};
65+
66+
const styles = StyleSheet.create({
67+
card: {
68+
backgroundColor: "rgba(255, 255, 255, 0.95)",
69+
borderRadius: 8,
70+
shadowColor: "#000",
71+
shadowOffset: {
72+
width: 0,
73+
height: 2,
74+
},
75+
shadowOpacity: 0.1,
76+
shadowRadius: 3,
77+
elevation: 3,
78+
padding: 16,
79+
position: "relative",
80+
},
81+
closeButton: {
82+
position: "absolute",
83+
right: 8,
84+
top: 8,
85+
padding: 4,
86+
zIndex: 1,
87+
},
88+
});
89+
90+
export default OCard;

mobile/components/OFloatingActionButton/OFloatingActionButton.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ interface OFloatingActionButtonProps {
1515
action: () => void;
1616
color: string;
1717
style?: ViewStyle;
18-
position?: "bottomRight" | "bottomLeft" | "topRight" | "topLeft";
18+
position?: "bottomRight" | "bottomLeft" | "topRight" | "topLeft" | "right";
1919
size: "md" | "xs";
2020
}
2121

@@ -31,6 +31,10 @@ export const OFloatingActionButton: React.FC<OFloatingActionButtonProps> = ({
3131
}) => {
3232
const getPositionStyle = (): ViewStyle => {
3333
switch (position) {
34+
case "right":
35+
return {
36+
right: width * positionDistance,
37+
};
3438
case "bottomRight":
3539
return {
3640
bottom: height * positionDistance,

mobile/components/OMap/OMap.tsx

Lines changed: 83 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,26 @@ import React, {
2424
useRef,
2525
useState,
2626
} from "react";
27-
import { StyleSheet, Text, TouchableWithoutFeedback, View } from "react-native";
27+
import {
28+
Dimensions,
29+
StyleSheet,
30+
Text,
31+
TouchableWithoutFeedback,
32+
View,
33+
} from "react-native";
2834
import BackgroundGeolocation from "react-native-background-geolocation";
2935
import MapView, { LongPressEvent, Region } from "react-native-maps";
36+
import { SafeAreaView } from "react-native-safe-area-context";
3037
import { TourGuideZone, useTourGuideController } from "rn-tourguide";
38+
import OCard from "../OCard/OCard";
3139

3240
interface OMapProps {
3341
saveChangesToBackend: boolean;
3442
showHeatmap: boolean;
3543
showBlacklistedRegions: boolean;
3644
}
3745

38-
const DEFAULT_RADIUS_SIZE = 1000;
46+
const DEFAULT_RADIUS_SIZE = 250;
3947

4048
export const OMap = (props: OMapProps) => {
4149
const { saveChangesToBackend, showHeatmap, showBlacklistedRegions } = props;
@@ -210,15 +218,17 @@ export const OMap = (props: OMapProps) => {
210218
zone={3}
211219
tourKey={TOURKEY.FIND}
212220
text={i18n.t(TR.tourSafeZones)}
221+
tooltipBottomOffset={-200}
213222
shape="rectangle"
214223
>
215-
<View style={styles.container}>
216-
<TourGuideZone
217-
zone={2}
218-
tourKey={TOURKEY.FIND}
219-
text={i18n.t(TR.tourHeatMap)}
220-
shape="rectangle"
221-
>
224+
<TourGuideZone
225+
zone={2}
226+
tourKey={TOURKEY.FIND}
227+
text={i18n.t(TR.tourHeatMap)}
228+
tooltipBottomOffset={-200}
229+
shape="rectangle"
230+
>
231+
<View style={styles.container}>
222232
<MapView
223233
style={styles.map}
224234
region={mapRegion}
@@ -248,33 +258,33 @@ export const OMap = (props: OMapProps) => {
248258
{showBlacklistedRegions &&
249259
renderedBlacklistedRegions}
250260
</MapView>
251-
</TourGuideZone>
252-
{showBlacklistedRegions && activeRegionIndex !== null && (
253-
<OFloatingActionButton
254-
size="xs"
255-
style={styles.fab}
256-
icon="delete-outline"
257-
action={() => handleRemoveRegion()}
258-
color={Color.red}
259-
/>
260-
)}
261-
{showBlacklistedRegions && (
262-
<View style={styles.instructions}>
263-
<Text style={[Subtitle, styles.instructionText]}>
264-
{i18n.t(TR.longPressMapSafeZoneInstruction)}
265-
</Text>
266-
</View>
267-
)}
268-
{showBlacklistedRegions && activeRegionIndex !== null && (
269-
<View style={styles.sliderContainer}>
270-
<Text style={[Subtitle, styles.sliderText]}>
271-
{i18n.t(TR.adjustRegionRadius)} (
272-
{Math.round(
273-
state.blacklistedRegions[activeRegionIndex]
274-
?.radius,
275-
)}
276-
m)
277-
</Text>
261+
</View>
262+
</TourGuideZone>
263+
264+
{showBlacklistedRegions && activeRegionIndex !== null && (
265+
<SafeAreaView
266+
edges={["bottom", "right", "left"]}
267+
style={styles.overlay}
268+
>
269+
<OCard style={styles.controlsCard}>
270+
<View style={styles.controlsHeader}>
271+
<Text style={[Subtitle, styles.sliderText]}>
272+
{i18n.t(TR.adjustRegionRadius)} (
273+
{Math.round(
274+
state.blacklistedRegions[
275+
activeRegionIndex
276+
]?.radius,
277+
)}
278+
m)
279+
</Text>
280+
<OFloatingActionButton
281+
size="xs"
282+
icon="delete-outline"
283+
position="right"
284+
action={handleRemoveRegion}
285+
color={Color.red}
286+
/>
287+
</View>
278288
<Slider
279289
style={styles.slider}
280290
minimumValue={100}
@@ -283,29 +293,25 @@ export const OMap = (props: OMapProps) => {
283293
value={tempSliderValue}
284294
onValueChange={handleRadiusChange}
285295
/>
286-
</View>
287-
)}
288-
</View>
296+
</OCard>
297+
</SafeAreaView>
298+
)}
289299
</TourGuideZone>
290300
</TouchableWithoutFeedback>
291301
);
292302
};
293303

304+
const { width, height } = Dimensions.get("window");
294305
const styles = StyleSheet.create({
295-
container: {
296-
flex: 1,
297-
position: "relative",
298-
},
299-
fab: {
300-
position: "absolute",
301-
top: 10,
302-
left: 10,
303-
zIndex: 1000,
304-
},
305306
map: {
306-
width: "100%",
307307
minHeight: 400,
308308
borderRadius: BorderRadius.br_5xs,
309+
position: "absolute",
310+
top: 0,
311+
left: 0,
312+
width,
313+
height,
314+
backgroundColor: Color.white,
309315
},
310316
instructions: {
311317
marginTop: 20,
@@ -314,18 +320,39 @@ const styles = StyleSheet.create({
314320
marginBottom: 5,
315321
fontSize: FontSize.size_sm,
316322
},
317-
sliderContainer: {
318-
marginTop: 20,
323+
controlsCard: {
324+
position: "absolute",
325+
bottom: 20,
326+
left: 20,
327+
right: 20,
328+
padding: 16,
329+
},
330+
controlsHeader: {
331+
flexDirection: "row",
332+
justifyContent: "space-between",
333+
alignItems: "center",
334+
marginBottom: 10,
319335
},
320336
sliderText: {
321337
fontSize: FontSize.size_md,
322-
marginBottom: 5,
338+
flex: 1,
339+
marginRight: 16,
323340
},
324341
slider: {
325342
width: "100%",
326343
},
327-
sliderValue: {
328-
color: Color.white,
329-
textAlign: "center",
344+
overlay: {
345+
position: "absolute",
346+
top: height / 1.5,
347+
left: 0,
348+
right: 0,
349+
zIndex: 1,
350+
},
351+
container: {
352+
flex: 1,
353+
width: "100%",
354+
height: "100%",
355+
position: "relative",
356+
minHeight: height * 0.75,
330357
},
331358
});

0 commit comments

Comments
 (0)