import React, { useState, useEffect } from 'react'; // ADDED useEffect import { // Ensure all necessary components are imported View, Text, TouchableOpacity, Image, Alert, StyleSheet, TextInput, ScrollView, ActivityIndicator, } from 'react-native'; import * as ImagePicker from 'expo-image-picker'; import { Ionicons } from '@expo/vector-icons'; import { useLocalSearchParams } from 'expo-router'; // ADDED: Import useLocalSearchParams interface UploadResponse { success: boolean; message: string; imageUrl?: string; } export default function UploadTab() { // Get parameters from the route const params = useLocalSearchParams(); // Ensure placeId from params is treated as a string, provide fallback if not present const initialPlaceId = typeof params.placeId === 'string' ? params.placeId : ''; const initialPlaceName = typeof params.placeName === 'string' ? params.placeName : 'Selected Place'; // For display const [selectedImage, setSelectedImage] = useState(null); // Initialize placeId state with the value from params const [placeId, setPlaceId] = useState(initialPlaceId); const [placeNameDisplay, setPlaceNameDisplay] = useState(initialPlaceName); // State for displaying name const [notes, setNotes] = useState(''); const [uploading, setUploading] = useState(false); const BACKEND_URL = 'http://132.145.65.145:8080'; // Use useEffect to update placeId and placeNameDisplay if params change // This handles cases where the component might already be mounted and params are updated useEffect(() => { if (typeof params.placeId === 'string' && params.placeId !== placeId) { setPlaceId(params.placeId); } if (typeof params.placeName === 'string' && params.placeName !== placeNameDisplay) { setPlaceNameDisplay(params.placeName); } }, [params.placeId, params.placeName]); // Depend on params.placeId and placeName const pickImage = async () => { const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync(); if (status !== 'granted') { Alert.alert('Permission Required', 'Sorry, we need camera roll permissions to upload images.'); return; } const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, // Use MediaTypeOptions.Images directly allowsEditing: true, aspect: [4, 3], quality: 0.8, allowsMultipleSelection: false, }); if (!result.canceled && result.assets && result.assets.length > 0) { setSelectedImage(result.assets[0].uri); } }; const takePhoto = async () => { const { status } = await ImagePicker.requestCameraPermissionsAsync(); if (status !== 'granted') { Alert.alert('Permission Required', 'Sorry, we need camera permissions to take photos.'); return; } const result = await ImagePicker.launchCameraAsync({ allowsEditing: true, aspect: [4, 3], quality: 0.8, }); if (!result.canceled && result.assets && result.assets.length > 0) { setSelectedImage(result.assets[0].uri); } }; const uploadImage = async () => { if (!selectedImage) { Alert.alert('Error', 'Please select an image first'); return; } if (!placeId) { // Ensure placeId is not empty after potential navigation Alert.alert('Error', 'Place ID is missing. Please select a mosque first.'); return; } setUploading(true); try { console.log('Uploading for placeId:', placeId); console.log('Notes:', notes); const formData = new FormData(); const imageFile = { uri: selectedImage, type: 'image/jpeg', name: 'image.jpg', } as any; formData.append('image', imageFile); formData.append('place_id', placeId.trim()); // Ensure this matches backend expected field name formData.append('Notes', notes.trim()); // Ensure this matches backend expected field name console.log('Sending form data with keys:', Array.from(formData.keys())); for (let [key, value] of formData.entries()) { console.log(key, value); } const response = await fetch(`${BACKEND_URL}/images/upload`, { method: 'POST', body: formData, headers: { 'Accept': 'application/json', // DO NOT set 'Content-Type' for FormData, fetch sets it automatically with boundary }, }); let result: UploadResponse; const responseCopy = response.clone(); // Clone response to read body twice if needed try { result = await response.json(); } catch (error) { const text = await responseCopy.text(); throw new Error(text || "Unknown error parsing JSON response"); } if (response.ok && result.success) { Alert.alert('Success', 'Image uploaded successfully!'); setSelectedImage(null); setPlaceId(initialPlaceId); // Reset to initial placeId from params, or empty if not from params setPlaceNameDisplay(initialPlaceName); // Reset display name setNotes(''); } else { Alert.alert('Upload Failed', result.message || 'Failed to upload image. Please check backend logs.'); } } catch (error) { console.error('Upload error:', error); Alert.alert('Error', `Upload failed: ${error.message || 'Network error'}.`); } finally { setUploading(false); } }; const clearImage = () => { setSelectedImage(null); }; return ( Upload Image {/* Display Place Name (User friendly) */} For: {placeNameDisplay || 'No place selected'} {/* Image Selection Section */} {selectedImage ? ( ) : ( No image selected )} {/* Image Selection Buttons */} Gallery Camera {/* Form Section */} Notes {/* Upload Button */} {uploading ? ( ) : ( <> Upload Image )} {/* Instructions */} Instructions: 1. Select an image from your gallery or take a photo{'\n'} 2. Add optional notes{'\n'} 3. Tap Upload ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#f8f9fa', }, contentContainer: { padding: 20, }, title: { fontSize: 24, fontWeight: 'bold', marginBottom: 20, textAlign: 'center', color: '#333', }, placeNameDisplay: { // New style to display the place name fontSize: 18, fontWeight: 'bold', marginBottom: 15, textAlign: 'center', color: '#555', }, imageSection: { marginBottom: 20, }, imageContainer: { position: 'relative', alignItems: 'center', }, selectedImage: { width: 300, height: 200, borderRadius: 10, resizeMode: 'cover', }, clearButton: { position: 'absolute', top: 10, right: 10, backgroundColor: '#fff', borderRadius: 12, }, placeholderContainer: { height: 200, backgroundColor: '#f0f0f0', borderRadius: 10, borderWidth: 2, borderColor: '#ddd', borderStyle: 'dashed', justifyContent: 'center', alignItems: 'center', }, placeholderText: { marginTop: 10, color: '#999', fontSize: 16, }, buttonRow: { flexDirection: 'row', justifyContent: 'space-around', marginBottom: 30, }, actionButton: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#e3f2fd', paddingHorizontal: 20, paddingVertical: 12, borderRadius: 8, borderWidth: 1, borderColor: '#007AFF', }, buttonText: { marginLeft: 8, color: '#007AFF', fontSize: 16, fontWeight: '500', }, formSection: { marginBottom: 30, }, label: { fontSize: 16, fontWeight: '600', marginBottom: 8, color: '#333', }, input: { backgroundColor: '#fff', borderWidth: 1, borderColor: '#ddd', borderRadius: 8, paddingHorizontal: 15, paddingVertical: 12, fontSize: 16, marginBottom: 15, }, readOnlyInput: { // NEW STYLE for read-only text input backgroundColor: '#e9ecef', // Lighter background for read-only color: '#6c757d', // Slightly greyed out text }, notesInput: { height: 80, paddingTop: 12, }, uploadButton: { backgroundColor: '#28a745', flexDirection: 'row', alignItems: 'center', justifyContent: 'center', paddingVertical: 15, borderRadius: 8, marginBottom: 30, }, uploadButtonDisabled: { backgroundColor: '#ccc', }, uploadButtonText: { color: '#fff', fontSize: 18, fontWeight: 'bold', marginLeft: 8, }, instructionsContainer: { backgroundColor: '#fff', padding: 15, borderRadius: 8, borderLeftWidth: 4, borderLeftColor: '#007AFF', }, instructionsTitle: { fontSize: 16, fontWeight: 'bold', marginBottom: 8, color: '#333', }, instructionsText: { fontSize: 14, color: '#666', lineHeight: 20, }, });