import AsyncStorage from "@react-native-async-storage/async-storage"; import { useRouter } from "expo-router"; import React, { useEffect, useState } from "react"; import { Alert, ImageBackground, KeyboardAvoidingView, Platform, ScrollView, Text, TextInput, TouchableOpacity, View } from "react-native"; import { SafeAreaView } from "react-native-safe-area-context"; import { styles } from "./styles"; const converterBgImage = require("../assets/images/saved-coordinates.jpg"); // Define a type for a single coordinate entry interface Coordinate { id: string; name: string; x: string; y: string; z: string; } export default function CoordinateConverter() { const router = useRouter(); // State for the list of saved coordinates const [savedCoordinates, setSavedCoordinates] = useState( [] ); // State for new coordinate input fields const [name, setName] = useState(""); const [xCoord, setXCoord] = useState(""); const [yCoord, setYCoord] = useState(""); const [zCoord, setZCoord] = useState(""); // Key for AsyncStorage const STORAGE_KEY = "@saved_minecraft_coordinates"; // Persistence Logic // Load coordinates from AsyncStorage on component mount useEffect(() => { loadCoordinates(); }, []); // Save coordinates to AsyncStorage useEffect(() => { saveCoordinates(); }, [savedCoordinates]); const loadCoordinates = async () => { try { const jsonValue = await AsyncStorage.getItem(STORAGE_KEY); if (jsonValue != null) { const parsedValue = JSON.parse(jsonValue) as Coordinate[]; if (Array.isArray(parsedValue)) { setSavedCoordinates(parsedValue); } else { console.warn( "Loaded data is not an array, initializing with empty array." ); setSavedCoordinates([]); } } } catch (e) { console.error("Failed to load coordinates:", e); Alert.alert( "Error", "Failed to load saved coordinates. Please try again." ); } }; const saveCoordinates = async () => { try { const jsonValue = JSON.stringify(savedCoordinates); await AsyncStorage.setItem(STORAGE_KEY, jsonValue); } catch (e) { console.error("Failed to save coordinates:", e); Alert.alert( "Error", "Failed to save coordinates. Please try again." ); } }; // Coordinate Logic const handleAddCoordinate = () => { const trimmedName = name.trim(); const trimmedX = xCoord.trim(); const trimmedY = yCoord.trim(); const trimmedZ = zCoord.trim(); const integerRegex = /^-?\d+$/; if ( !integerRegex.test(trimmedX) || !integerRegex.test(trimmedY) || !integerRegex.test(trimmedZ) ) { Alert.alert( "Invalid Input", "Please enter valid integer numbers for X, Y, and Z (e.g., 100, -50). Decimals or non-numeric characters are not allowed." ); return; } const newCoordinate: Coordinate = { id: Date.now().toString(), name: trimmedName || `Unnamed Location ${savedCoordinates.length + 1}`, x: trimmedX, y: trimmedY, z: trimmedZ }; setSavedCoordinates((prevCoords) => [...prevCoords, newCoordinate]); // Clear input fields setName(""); setXCoord(""); setYCoord(""); setZCoord(""); }; const handleDeleteCoordinate = (id: string) => { Alert.alert( "Delete Coordinate", "Are you sure you want to delete this coordinate?", [ { text: "Cancel", style: "cancel" }, { text: "Delete", onPress: () => { setSavedCoordinates((prevCoords) => prevCoords.filter((coord) => coord.id !== id) ); }, style: "destructive" } ], { cancelable: true } ); }; return ( {/* Custom Back Button */} router.back()} style={styles.backButton} > ← Go Back Saved Coordinates {/* Coordinate Input Section */} Save Coordinate {/* Coordinate List Display */} {savedCoordinates.length === 0 ? ( No coordinates saved yet. ) : ( savedCoordinates.map((coord) => ( {coord.name} X: {coord.x}, Y: {coord.y}, Z:{" "} {coord.z} handleDeleteCoordinate(coord.id) } style={styles.removeCoordinateButton} > X )) )} ); }