import React, { useState, useEffect } from 'react'; import { View, Text, TextInput, Image, TouchableOpacity, Alert, useWindowDimensions, Modal, ImageBackground, Platform, ActivityIndicator, Switch, } from 'react-native'; // KeyboardAwareScrollView entfernt - Scrolling wird jetzt in der Parent-Komponente implementiert import { BlurView } from 'expo-blur'; import * as ImagePicker from 'expo-image-picker'; import FontAwesome from '@expo/vector-icons/FontAwesome'; import { useTheme } from '~/utils/ThemeContext'; import { generateFigure } from '~/utils/figureService'; import { useAuth } from '~/utils/AuthContext'; import { router } from 'expo-router'; // FigureData Typ-Definition interface FigureData { name: string; characterDescription: string; characterImage: string | null; artifacts: Array<{ name?: string; // Neues Feld für den Namen des Artefakts description: string; image: string | null; }>; } // Erweiterte FigureData mit Rarität export type ExtendedFigureData = FigureData & { rarity?: string; // Rarität der Figur (z.B. 'common', 'rare', 'legendary') }; interface ArtifactData { name?: string; // Neues Feld für den Namen des Artefakts description: string; image: string | null; } interface SidebarCreateFigureFormProps { onSubmit?: (handleSubmit: () => Promise) => void; } export const SidebarCreateFigureForm: React.FC = ({ onSubmit }) => { const { theme, isDark } = useTheme(); const { width, height } = useWindowDimensions(); const { user } = useAuth(); // Determine if we're in wide screen mode (tablet/desktop) const isWideScreen = width > 768; // Calculate half of the screen height for initial scroll distance const halfScreenHeight = height / 2; // Check if we're running in a web environment const isWeb = Platform.OS === 'web'; // State for tracking which input is focused const [focusedInput, setFocusedInput] = useState< 'character' | 'name' | `artifact-${number}` | null >(null); // State für den Generierungsprozess const [isGenerating, setIsGenerating] = useState(false); // State für die Sichtbarkeit der Figur const [isPublic, setIsPublic] = useState(true); // Initialize form state with empty values - only name is required const [formData, setFormData] = useState({ name: '', characterDescription: '', characterImage: null, artifacts: [ { description: '', image: null }, { description: '', image: null }, { description: '', image: null }, ], }); // State for description modals const [descriptionModalVisible, setDescriptionModalVisible] = useState(false); const [currentDescriptionType, setCurrentDescriptionType] = useState<'character' | 'artifact'>( 'character' ); const [currentArtifactIndex, setCurrentArtifactIndex] = useState(0); // Handle name change const handleNameChange = (text: string) => { setFormData({ ...formData, name: text, }); }; // Handle character description change const handleCharacterDescriptionChange = (text: string) => { setFormData({ ...formData, characterDescription: text, }); }; // Handle artifact description change const handleArtifactDescriptionChange = (index: number, text: string) => { const updatedArtifacts = [...formData.artifacts]; updatedArtifacts[index] = { ...updatedArtifacts[index], description: text, }; setFormData({ ...formData, artifacts: updatedArtifacts, }); }; // Pick an image from the gallery const pickImage = async (type: 'character' | number) => { try { // Berechtigungen prüfen const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync(); if (status !== 'granted') { Alert.alert( 'Berechtigung verweigert', 'Wir benötigen Zugriff auf deine Fotos, um ein Bild auszuwählen.' ); return; } // Bild auswählen const result = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images, allowsEditing: true, aspect: [1, 1], quality: 0.8, }); if (!result.canceled && result.assets && result.assets.length > 0) { const selectedImage = result.assets[0].uri; // Update state based on type if (type === 'character') { setFormData({ ...formData, characterImage: selectedImage, }); } else if (typeof type === 'number') { const updatedArtifacts = [...formData.artifacts]; updatedArtifacts[type] = { ...updatedArtifacts[type], image: selectedImage, }; setFormData({ ...formData, artifacts: updatedArtifacts, }); } } } catch (error) { console.error('Error picking image:', error); Alert.alert('Fehler', 'Es gab ein Problem beim Auswählen des Bildes.'); } }; // Handle form submission const handleSubmit = async () => { // Validate form - only name is required if (!formData.name.trim()) { Alert.alert('Error', 'Please enter a name for your figure.'); return; } // All other fields are optional and will be generated by the LLM if missing if (!user) { Alert.alert('Fehler', 'Du musst eingeloggt sein, um eine Figur zu erstellen.'); return; } try { setIsGenerating(true); // Figur generieren const figure = await generateFigure(formData, isPublic); // Erfolgsmeldung anzeigen Alert.alert('Success!', 'Your action figure has been created!', [ { text: 'Go to My Shelf', onPress: () => router.replace('/(tabs)'), }, { text: 'OK', style: 'cancel', }, ]); // Formular zurücksetzen setFormData({ name: '', characterDescription: '', characterImage: null, artifacts: [ { description: '', image: null }, { description: '', image: null }, { description: '', image: null }, ], }); } catch (error) { console.error('Error creating figure:', error); Alert.alert('Error', 'There was a problem creating your figure. Please try again.'); } finally { setIsGenerating(false); } }; // Render description modal const renderDescriptionModal = () => { const isCharacter = currentDescriptionType === 'character'; const currentDescription = isCharacter ? formData.characterDescription : formData.artifacts[currentArtifactIndex].description; return ( setDescriptionModalVisible(false)} > {isCharacter ? 'Character Description' : `Artifact ${currentArtifactIndex + 1} Description`} { if (isCharacter) { handleCharacterDescriptionChange(text); } else { handleArtifactDescriptionChange(currentArtifactIndex, text); } }} /> setDescriptionModalVisible(false)} > Cancel { setDescriptionModalVisible(false); }} > Save ); }; // Render the form content directly without the outer container const renderFormContent = () => { return ( {/* Name Input and Image Upload */} setFocusedInput('name')} onBlur={() => setFocusedInput(null)} onChangeText={handleNameChange} autoCapitalize="words" autoCorrect={false} /> {/* Image Upload Button */} pickImage('character')} > {formData.characterImage ? ( ) : ( <> Image )} {/* Eingabefelder */} {/* Character Beschreibung */} setFocusedInput('character')} onBlur={() => setFocusedInput(null)} onChangeText={handleCharacterDescriptionChange} /> {/* Character Bild Upload removed - now next to name */} {/* Sichtbarkeit - nach oben verschoben - mit negativem Margin für engeren Abstand */} Publish Figgo {/* Divider über Artefakten */} {/* Artefakt Beschreibungen */} {[0, 1, 2].map((index) => ( setFocusedInput(`artifact-${index}` as any)} onBlur={() => setFocusedInput(null)} onChangeText={(text) => handleArtifactDescriptionChange(index, text)} /> ))} {/* Divider unter Artefakten */} ); }; // Expose the handleSubmit function to the parent component // Verwende useEffect mit vollständiger Dependency-Liste, um sicherzustellen, // dass der Handler aktualisiert wird, wenn sich formData oder isPublic ändert React.useEffect(() => { if (onSubmit) { onSubmit(handleSubmit); } }, [onSubmit, handleSubmit, formData, isPublic]); // Stelle sicher, dass der Handler sofort beim ersten Rendern verfügbar ist React.useEffect(() => { if (onSubmit) { onSubmit(handleSubmit); } }, []); return ( {isWeb ? ( {renderFormContent()} ) : Platform.OS === 'ios' ? ( {renderFormContent()} ) : ( {renderFormContent()} )} {/* Description Modal */} {renderDescriptionModal()} ); }; export default SidebarCreateFigureForm;