diff --git a/app/(tabs)/add.jsx b/app/(tabs)/add.jsx index 48893bd..35f94eb 100644 --- a/app/(tabs)/add.jsx +++ b/app/(tabs)/add.jsx @@ -1,10 +1,11 @@ import { useState } from 'react'; import { StyleSheet, Platform, KeyboardAvoidingView, ScrollView } from 'react-native'; -import { TextInput, Button, Snackbar } from 'react-native-paper'; -import { locations } from '@/data/locations'; - +import { TextInput, Button, Snackbar } from 'react-native-paper'; +import useLocationStore from '@/store'; export default function FormScreen() { + const addLocation = useLocationStore((state) => state.addLocation); + const [formData, setFormData] = useState({ name: '', description: '', @@ -15,13 +16,16 @@ export default function FormScreen() { const [message, setMessage] = useState(''); const [visible, setVisible] = useState(false); - const [location, setLocation] = useState(locations.sort((a, b) => b.id - a.id)); - - const addLocation = () => { - console.log(formData); - if(formData.name && formData.description && formData.image && formData.area && formData.population) { + const handleAddLocation = () => { + if ( + formData.name && + formData.description && + formData.image && + formData.area && + formData.population + ) { const newLocation = { - id: locations.length > 0 ? locations[0].id + 1 : 0, + id: Date.now(), // Generowanie unikalnego ID name: formData.name, description: formData.description, image: formData.image, @@ -29,9 +33,7 @@ export default function FormScreen() { population: formData.population, }; - setLocation([newLocation, ...location]); - - locations.push(newLocation); + addLocation(newLocation); setFormData({ name: '', @@ -42,75 +44,75 @@ export default function FormScreen() { }); setMessage('Lokalizacja została dodana!'); setVisible(true); - }else{ + } else { setMessage('Wypełnij wszystkie pola!'); setVisible(true); } - } + }; return ( - - setVisible(false)} - duration={3000} - > - {message} - + style={{ flex: 1 }} + behavior={Platform.OS === 'ios' ? 'padding' : 'height'} + > + + setVisible(false)} + duration={3000} + > + {message} + setFormData({ ...formData, name: e })} - - /> - setFormData({ ...formData, name: e })} + /> + setFormData({ ...formData, description: e })} - /> - setFormData({ ...formData, description: e })} + /> + setFormData({ ...formData, image: e })} - /> + onChangeText={(e) => setFormData({ ...formData, image: e })} + /> setFormData({ ...formData, area: e })} + onChangeText={(e) => setFormData({ ...formData, area: e })} /> setFormData({ ...formData, population: e })} + keyboardType="numeric" + onChangeText={(e) => setFormData({ ...formData, population: e })} /> - - + onPress={handleAddLocation} + > + Dodaj + ); @@ -123,7 +125,4 @@ const styles = StyleSheet.create({ justifyContent: 'flex-start', alignItems: 'center', }, - text: { - color: '#fff', - }, -}); +}); \ No newline at end of file diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx index 76034b3..3be9b20 100644 --- a/app/(tabs)/index.tsx +++ b/app/(tabs)/index.tsx @@ -1,31 +1,32 @@ import { View, StyleSheet, FlatList } from 'react-native'; -import { useTheme, Card, Text, Button} from 'react-native-paper'; +import { useTheme, Card, Text, Button } from 'react-native-paper'; import { Link } from 'expo-router'; -import { locations } from '@/data/locations'; +import useLocationStore from '@/store'; export default function Index() { -const theme = useTheme(); -locations.sort((a, b) => b.id - a.id); + const theme = useTheme(); + const locations = useLocationStore((state) => state.locations); + return ( - - + item.name} + keyExtractor={(item) => item.id.toString()} renderItem={({ item }) => ( - - - + + + {item.name} {item.description.split('.')[0]}... - - + + - )}> - + )} + /> ); } @@ -37,7 +38,4 @@ const styles = StyleSheet.create({ justifyContent: 'center', alignItems: 'center', }, - text: { - color: '#fff', - }, -}); +}); \ No newline at end of file diff --git a/app/_layout.jsx b/app/_layout.jsx index 87de867..d9f3d42 100644 --- a/app/_layout.jsx +++ b/app/_layout.jsx @@ -1,13 +1,21 @@ -import { Link, Stack } from 'expo-router'; -import { useColorScheme } from 'react-native'; +import { Link, Stack, useRouter } from 'expo-router'; +import { useColorScheme} from 'react-native'; import { PaperProvider} from 'react-native-paper'; import { MD3LightTheme, MD3DarkTheme } from 'react-native-paper'; import Ionicons from '@expo/vector-icons/Ionicons'; +import useLocationStore from '@/store'; export default function RootLayout() { const colorScheme = useColorScheme(); const theme = colorScheme === 'dark' ? MD3DarkTheme : MD3LightTheme; + const deleteLocation = useLocationStore((state) => state.deleteLocation); + const router = useRouter(); + + const handleDelete = (id) => { + deleteLocation(id); + router.replace('/'); + }; return ( @@ -35,7 +43,12 @@ export default function RootLayout() { ), })} /> - + ({ title: "Edycja", + headerRight: () => ( + handleDelete(route.params.id)}/> + ), })} + + /> ); diff --git a/app/location/[id].js b/app/location/[id].js index a273e42..b3e40d2 100644 --- a/app/location/[id].js +++ b/app/location/[id].js @@ -1,50 +1,51 @@ import { View, ScrollView, StyleSheet } from 'react-native'; import { Text, Card } from 'react-native-paper'; import { useLocalSearchParams } from 'expo-router'; -import { locations } from '@/data/locations'; +import useLocationStore from '@/store'; export default function Location() { const { id } = useLocalSearchParams(); - const location = locations.find(loc => loc.id == id); + const location = useLocationStore((state) => + state.locations.find((loc) => loc.id == id) + ); if (!location) { return ( - Brak lokalizaji - {id} + Brak lokalizacji - {id} ); } return ( - - - - - - {location.name} - - - Opis: - - - {location.description} - - + + + + + + {location.name} + + + Opis: + + {location.description} + - - - Statystyki: - - - Powierzchnia: {location.area} km² + + + Statystyki: - - Ludność: {location.population} osób + + Powierzchnia: {location.area} km² - - - + + Ludność: {location.population} osób + + + + + ); } @@ -58,4 +59,4 @@ const styles = StyleSheet.create({ text: { color: '#fff', }, -}); +}); \ No newline at end of file diff --git a/app/location/edit/[id].js b/app/location/edit/[id].js index b31a702..e4ead45 100644 --- a/app/location/edit/[id].js +++ b/app/location/edit/[id].js @@ -1,126 +1,131 @@ import { useState, useEffect } from 'react'; import { StyleSheet, Platform, ScrollView, KeyboardAvoidingView } from 'react-native'; -import { TextInput, Button, Snackbar } from 'react-native-paper'; -import { locations } from '@/data/locations'; +import { TextInput, Button, Snackbar } from 'react-native-paper'; import { useLocalSearchParams, useRouter } from 'expo-router'; +import useLocationStore from '@/store'; -export default function edit() { - const { id } = useLocalSearchParams(); - const router = useRouter(); - const locationData = locations.find(loc => loc.id == id); - const [formData, setFormData] = useState({ - name: '', - description: '', - image: '', - area: '', - population: '', - }); +export default function EditLocation() { + const { id } = useLocalSearchParams(); + const router = useRouter(); + const location = useLocationStore((state) => + state.locations.find((loc) => loc.id == id) + ); + const updateLocation = useLocationStore((state) => state.updateLocation); - const [message, setMessage] = useState(''); - const [visible, setVisible] = useState(false); + const [formData, setFormData] = useState({ + name: '', + description: '', + image: '', + area: '', + population: '', + }); - useEffect(() => { - if (locationData) { - console.log(locationData); - setFormData({ - name: locationData.name, - description: locationData.description, - image: locationData.image, - area: locationData.area.toString(), - population: locationData.population.toString(), - }); - } - }, [locationData]); + const [message, setMessage] = useState(''); + const [visible, setVisible] = useState(false); + useEffect(() => { + if (location) { + setFormData({ + name: location.name, + description: location.description, + image: location.image, + area: location.area.toString(), + population: location.population.toString(), + }); + } + }, [location]); - const editLocation = () => { - if ( - formData.name && - formData.description && - formData.image && - formData.area && - formData.population - ) { - const index = locations.findIndex((loc) => loc.id == id); - if (index !== -1) { - locations[index] = { ...locations[index], ...formData }; - setMessage('Lokalizacja została zaktualizowana!'); - setVisible(true); - }else{ - setMessage('Błąd spróbuj ponownie póżniej!'); - setVisible(true); - } - } else{ - setMessage('Wypełnij wszystkie pola!'); - setVisible(true); - } - }; + const handleEditLocation = () => { + if ( + formData.name && + formData.description && + formData.image && + formData.area && + formData.population + ) { + updateLocation(id, { + name: formData.name, + description: formData.description, + image: formData.image, + area: parseFloat(formData.area), + population: parseInt(formData.population, 10), + }); - + setMessage('Lokalizacja została zaktualizowana!'); + setVisible(true); + + // setTimeout(() => { + // router.replace(`/location/${id}`); + // }, 2000); + } else { + setMessage('Wypełnij wszystkie pola!'); + setVisible(true); + } + }; return ( - - setVisible(false)} - duration={3000} - > - {message} - + behavior={Platform.OS === 'ios' ? 'padding' : 'height'} + > + + setVisible(false)} + duration={3000} + > + {message} + setFormData({ ...formData, name: e })} - - /> - setFormData({ ...formData, name: e })} + /> + setFormData({ ...formData, description: e })} - /> - setFormData({ ...formData, description: e })} + /> + setFormData({ ...formData, image: e })} - /> + onChangeText={(e) => setFormData({ ...formData, image: e })} + /> setFormData({ ...formData, area: e })} + onChangeText={(e) => setFormData({ ...formData, area: e })} /> setFormData({ ...formData, population: e })} + keyboardType="numeric" + onChangeText={(e) => setFormData({ ...formData, population: e })} /> - - + onPress={handleEditLocation} + > + Edytuj + ); @@ -133,7 +138,4 @@ const styles = StyleSheet.create({ justifyContent: 'flex-start', alignItems: 'center', }, - text: { - color: '#fff', - }, -}); +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4d47cee..c8c6605 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,8 @@ "react-native-paper": "^5.13.1", "react-native-safe-area-context": "4.12.0", "react-native-screens": "~4.4.0", - "react-native-web": "~0.19.13" + "react-native-web": "~0.19.13", + "zustand": "^5.0.3" }, "devDependencies": { "@babel/core": "^7.20.0", @@ -11773,6 +11774,35 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zustand": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.3.tgz", + "integrity": "sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } } } } diff --git a/package.json b/package.json index dc0b11c..ce31258 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "react-native-paper": "^5.13.1", "react-native-safe-area-context": "4.12.0", "react-native-screens": "~4.4.0", - "react-native-web": "~0.19.13" + "react-native-web": "~0.19.13", + "zustand": "^5.0.3" }, "devDependencies": { "@babel/core": "^7.20.0", diff --git a/store.js b/store.js new file mode 100644 index 0000000..a7a7707 --- /dev/null +++ b/store.js @@ -0,0 +1,23 @@ +import { create } from 'zustand'; +import { locations as initialLocations } from '@/data/locations'; + +console.log('Initial locations:', initialLocations); +const useLocationStore = create((set) => ({ + locations: initialLocations, + addLocation: (newLocation) => + set((state) => ({ + locations: [newLocation, ...state.locations], + })), + updateLocation: (id, updatedData) => + set((state) => ({ + locations: state.locations.map((loc) => + loc.id == id ? { ...loc, ...updatedData } : loc + ), + })), + deleteLocation: (id) => + set((state) => ({ + locations: state.locations.filter((loc) => loc.id != id), + })), +})); + +export default useLocationStore; \ No newline at end of file