Files
CityExplorer/app/(tabs)/add.jsx
2025-05-23 21:19:11 +02:00

283 lines
9.4 KiB
JavaScript

import {useState} from "react";
import {
StyleSheet,
Platform,
KeyboardAvoidingView,
ScrollView,
Image,
View,
Alert,
} from "react-native";
import {TextInput, Button, Snackbar, Text, useTheme} from "react-native-paper";
import {requestCameraPermissionsAsync, launchCameraAsync} from 'expo-image-picker';
import * as Location from 'expo-location';
import useLocationStore from "@/locationStore";
export default function FormScreen() {
const [formData, setFormData] = useState({
name: "",
description: "",
image: "",
area: 0,
population: 0,
latitude: 0,
longitude: 0,
});
const [message, setMessage] = useState("");
const [visible, setVisible] = useState(false);
const [picture, setPicture] = useState(null);
const [imageMethod, setImageMethod] = useState(null);
const [location, setLocation] = useState < Location.LocationObject | null > (null);
const theme = useTheme();
const addLocation = useLocationStore((state) => state.addLocation);
const handleAddLocation = async () => {
if (
formData.name &&
formData.description &&
formData.image &&
formData.area &&
formData.population &&
formData.latitude &&
formData.longitude
) {
const newLocation = {
id: Date.now(),
name: formData.name,
description: formData.description,
image: formData.image,
area: parseFloat(formData.area),
population: parseInt(formData.population),
latitude: parseFloat(formData.latitude),
longitude: parseFloat(formData.longitude),
};
const added = await addLocation(newLocation);
setFormData({
name: "",
description: "",
image: "",
area: 0,
population: 0,
latitude: 0,
longitude: 0
});
setPicture(null);
setImageMethod(null);
if (added != null) {
setMessage("Lokalizacja została dodana!");
setVisible(true);
} else {
setMessage("Wystąpił błąd podczas dodawania lokalizacji!");
setVisible(true);
}
} else {
setMessage("Wypełnij wszystkie pola!");
console.log(formData);
setVisible(true);
}
};
const takePicture = async () => {
const {status} = await requestCameraPermissionsAsync();
if (status !== 'granted') {
setMessage("Brak uprawnień do kamery!");
setVisible(true);
return;
}
const result = await launchCameraAsync({
allowsEditing: false,
base64: true,
});
if (!result.canceled && result.assets && result.assets.length > 0) {
const image = result.assets[0];
setPicture(image.uri);
setFormData({...formData, image: image.base64});
}
}
async function getCurrentLocation() {
let {status} = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
console.log('Permission to access location was denied');
Alert.alert("Błąd", "Nie udało się uzyskać dostępu do pobierania lokalizacji");
return;
}
try {
let location = await Location.getCurrentPositionAsync({});
setLocation(location);
setFormData({
...formData,
latitude: location.coords.latitude,
longitude: location.coords.longitude
});
Alert.alert("Sukces!", "Pobrano lokalizację\n" +
"Szerokość geograficzna: " + location.coords.latitude + "\n" +
"Długość geograficzna: " + location.coords.longitude);
} catch (error) {
Alert.alert("Błąd", "Nie udało się pobrać lokalizacji");
console.error(error);
}
}
const selectImageMethod = (method) => {
setImageMethod(method);
if (method === 'camera') {
takePicture()
} else {
setFormData({...formData, image: ""});
setPicture(null);
}
}
return (
<KeyboardAvoidingView
style={{flex: 1}}
behavior={Platform.OS === "ios" ? "padding" : "height"}
>
<ScrollView contentContainerStyle={styles.container} contentInsetAdjustmentBehavior="automatic"
style={[{backgroundColor: theme.colors.background}]}
>
<Snackbar
visible={visible}
onDismiss={() => setVisible(false)}
duration={3000}
>
{message}
</Snackbar>
<Text style={styles.label} variant="labelLarge">Jak chcesz dodać zdjęcie?</Text>
<View style={styles.imageMethodButtons}>
<Button
mode={imageMethod === 'link' ? "contained" : "outlined"}
onPress={() => selectImageMethod('link')}
style={styles.methodButton}
>
Użyj linku
</Button>
<Button
mode={imageMethod === 'camera' ? "contained" : "outlined"}
onPress={() => selectImageMethod('camera')}
style={styles.methodButton}
>
Zrób zdjęcie
</Button>
</View>
{imageMethod === 'link' && (
<TextInput
mode="outlined"
label="Link do zdjęcia"
placeholder="Wpisz link do zdjęcia"
multiline={true}
style={{margin: 10, width: "100%"}}
value={formData.image}
onChangeText={(e) => setFormData({...formData, image: e})}
/>
)}
{picture && (
<View style={styles.imageContainer}>
<Image
source={{uri: picture}}
style={styles.image}
/>
</View>
)}
<TextInput
mode="outlined"
label="Nazwa"
placeholder="Wpisz nazwę"
style={{margin: 10, width: "100%"}}
value={formData.name}
onChangeText={(e) => setFormData({...formData, name: e})}
/>
<TextInput
mode="outlined"
label="Opis"
placeholder="Wpisz opis"
style={{margin: 10, width: "100%"}}
multiline={true}
value={formData.description}
onChangeText={(e) => setFormData({...formData, description: e})}
/>
<TextInput
mode="outlined"
label="Powierzchnia"
placeholder="Wpisz powierzchnię"
style={{margin: 10, width: "100%"}}
value={formData.area}
keyboardType="numbers-and-punctuation"
onChangeText={(e) => setFormData({...formData, area: e})}
/>
<TextInput
mode="outlined"
label="Ludność"
placeholder="Wpisz liczbę ludności"
style={{margin: 10, width: "100%"}}
value={formData.population}
keyboardType="numeric"
onChangeText={(e) => setFormData({...formData, population: e})}
/>
<Button
style={{margin: 10, width: "100%"}}
icon="plus-circle-outline"
mode={"contained"}
onPress={handleAddLocation}
>
Dodaj
</Button>
<Button
style={{margin: 10, width: "100%"}} mode={"contained"}
onPress={getCurrentLocation}
icon={location ? "check-circle-outline" : "map-marker-outline"}
>
Pobierz aktualną lokalizację
</Button>
</ScrollView>
</KeyboardAvoidingView>
);
}
const styles = StyleSheet.create({
container: {
// backgroundColor: "#25292e",
alignItems: "center",
padding: 10,
flexGrow: 1,
},
imageContainer: {
width: "100%",
alignItems: "flex-start",
marginVertical: 10,
},
image: {
width: 150,
height: 150,
borderStyle: "solid",
borderWidth: 1,
borderRadius: 5,
},
imageMethodButtons: {
flexDirection: 'row',
justifyContent: 'space-between',
width: '100%',
marginVertical: 10,
},
methodButton: {
flex: 1,
marginHorizontal: 5,
},
label: {
marginTop: 10,
marginBottom: 10,
verticalAlign: "middle",
textAlign: "center",
}
});