import React, { useState, useEffect } from "react"; import customRF from '../utils/customRF'; import { View, Text, StyleSheet, TextInput, TouchableOpacity, FlatList, KeyboardAvoidingView, Platform, ImageBackground, StatusBar, SafeAreaView, Modal, Animated } from "react-native"; import { useNavigation } from "@react-navigation/native"; import { NativeStackNavigationProp } from "@react-navigation/native-stack"; import { chatService } from "../services/api/chat"; import useUserStore from "../store/user"; import AsyncStorage from "@react-native-async-storage/async-storage"; import { useTranslation } from 'react-i18next'; interface Message { id?: string; mimetype: string; userWs: string; app_id: string; country: number; body: string; text: string; type: string; isMe?: boolean; timestamp?: Date; } type TabType = "customer" | "product" | "notification"; type RootStackParamList = { Login: undefined; // other screens... }; export const ChatScreen = () => { const [messages, setMessages] = useState([]); const [inputText, setInputText] = useState(""); const [activeTab, setActiveTab] = useState("customer"); const [loginModalVisible, setLoginModalVisible] = useState(false); const [country, setCountry] = useState(""); // Store the country code const { t } = useTranslation(); const { user } = useUserStore(); const navigation = useNavigation>(); // Add animation values const [fadeAnim] = useState(new Animated.Value(0)); const [slideAnim] = useState(new Animated.Value(300)); // Get country from AsyncStorage useEffect(() => { const getCountry = async () => { try { const selectedCountry = await AsyncStorage.getItem('@selected_country'); if (selectedCountry) { const countryData = JSON.parse(selectedCountry); setCountry(countryData.name_en || ""); } } catch (error) { console.error('Error getting country data:', error); } }; getCountry(); }, []); // Check if user is logged in useEffect(() => { if (!user.user_id) { setLoginModalVisible(true); // Animate modal appearance Animated.parallel([ Animated.timing(fadeAnim, { toValue: 1, duration: 300, useNativeDriver: true, }), Animated.spring(slideAnim, { toValue: 0, tension: 50, friction: 9, useNativeDriver: true, }) ]).start(); } else { setLoginModalVisible(false); } }, [user.user_id]); const handleCloseModal = () => { // Animate modal exit Animated.parallel([ Animated.timing(fadeAnim, { toValue: 0, duration: 200, useNativeDriver: true, }), Animated.timing(slideAnim, { toValue: 300, duration: 200, useNativeDriver: true, }) ]).start(() => { setLoginModalVisible(false); }); }; const handleGoToLogin = () => { handleCloseModal(); // Navigate to login after modal is closed setTimeout(() => { navigation.navigate('Login'); }, 200); }; const sendMessage = () => { if (inputText.trim() === "") return; const newMessage: Message = { mimetype: "text/plain", userWs: "unknown", app_id: user.user_id ? user.user_id.toString() : "", country: user.country_code, body: "", text: inputText, type: "text", isMe: true, timestamp: new Date(), id: Date.now().toString(), // Add unique id for keyExtractor }; // Extract only the properties that chatService.sendMessage expects const chatServiceMessage = { type: newMessage.type, mimetype: newMessage.mimetype, userWs: newMessage.userWs, app_id: newMessage.app_id, country: newMessage.country.toString(), body: newMessage.body, text: newMessage.text }; // Add user message to the chat UI setMessages([...messages, newMessage]); setInputText(""); // Add simulated response with loading indicator const simulatedId = `simulated-${Date.now()}`; const simulatedResponse: Message = { mimetype: "text/plain", userWs: "system", app_id: "system", country: user.country_code, body: "", text: `${t('typingMessage')}...`, type: "chat", isMe: false, timestamp: new Date(), id: simulatedId, }; // Add simulated message after a short delay to make it feel more natural setTimeout(() => { setMessages(prevMessages => [...prevMessages, simulatedResponse]); }, 800); const data = { newMessage:chatServiceMessage, } // Send actual message to API chatService.sendMessage(data) .then(response => { // When real response arrives, replace simulated message setMessages(prevMessages => { // Filter out the simulated message and add real response const filtered = prevMessages.filter(msg => msg.id !== simulatedId); // Create the real response message object const realResponse: Message = { mimetype: "text/plain", userWs: "system", app_id: "system", country: user.country_code, body: "", text: response?.reply || t('defaultResponse'), type: "chat", isMe: false, timestamp: new Date(), id: `real-${Date.now()}`, }; return [...filtered, realResponse]; }); }) .catch(error => { // In case of error, replace simulated message with error message console.error('Chat API error:', error); setMessages(prevMessages => { const filtered = prevMessages.filter(msg => msg.id !== simulatedId); const errorResponse: Message = { mimetype: "text/plain", userWs: "system", app_id: "system", country: user.country_code, body: "", text: t('errorResponse'), type: "chat", isMe: false, timestamp: new Date(), id: `error-${Date.now()}`, }; return [...filtered, errorResponse]; }); }); }; // Generate a unique key for each message const keyExtractor = (item: Message, index: number): string => { return item.id || index.toString(); }; const renderMessage = ({ item }: { item: Message }) => ( {item.text} {item.timestamp?.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", })} ); const renderTabContent = () => { switch (activeTab) { case "customer": return ( ); case "product": return ( ); case "notification": return ( ); } }; return ( setActiveTab("customer")} > {t('customerServiceChat')} setActiveTab("product")} > {t('productChat')} setActiveTab("notification")} > {t('notificationChat')} {renderTabContent()} {t('send')} {/* Login Modal */} {t('loginRequired')} {t('pleaseLoginToChat')} {t('loginNow')} ); }; const styles = StyleSheet.create({ safeArea: { flex: 1, backgroundColor: '#fff', }, safeAreaContent: { flex: 1, paddingTop: Platform.OS === 'android' ? 0 : 0, }, container: { flex: 1, backgroundColor: '#fff', }, backgroundImage: { flex: 1, width: '100%', height: '100%', }, tabBar: { flexDirection: "row", backgroundColor: "#007a6c", borderBottomWidth: 1, borderBottomColor: "#eef0f1", shadowColor: "#000", shadowOffset: { width: 0, height: 2, }, shadowOpacity: 0.25, shadowRadius: 3.84, elevation: 5, }, tab: { flex: 1, paddingVertical: 15, alignItems: "center", }, activeTab: { borderBottomWidth: 2, borderBottomColor: "#eef0f1", }, tabText: { fontSize: customRF(14), color: "#fff", }, activeTabText: { color: "#fff", fontWeight: "600", }, tabContent: { flex: 1, }, messageList: { padding: 10, }, messageContainer: { maxWidth: "80%", padding: 10, borderRadius: 10, marginVertical: 5, }, myMessage: { alignSelf: "flex-end", backgroundColor: "#dcf8c6", }, theirMessage: { alignSelf: "flex-start", backgroundColor: "white", }, messageText: { fontSize: 16, }, timestamp: { fontSize: 12, color: "#666", alignSelf: "flex-end", marginTop: 5, }, inputContainer: { flexDirection: "row", padding: 10, backgroundColor: "white", borderTopWidth: 1, borderTopColor: "#ddd", }, input: { flex: 1, backgroundColor: "#f0f0f0", borderRadius: 20, paddingHorizontal: 15, paddingVertical: 8, marginRight: 10, maxHeight: 100, }, sendButton: { backgroundColor: "#128C7E", borderRadius: 20, paddingHorizontal: 20, justifyContent: "center", }, sendButtonText: { color: "white", fontSize: 16, }, // Modal styles modalContainer: { flex: 1, justifyContent: 'flex-end', }, modalOverlay: { ...StyleSheet.absoluteFillObject, backgroundColor: 'rgba(0, 0, 0, 0.5)', }, modalOverlayTouch: { flex: 1, }, modalContent: { backgroundColor: '#fff', borderTopLeftRadius: 24, borderTopRightRadius: 24, paddingHorizontal: 20, paddingBottom: Platform.OS === 'ios' ? 40 : 20, position: 'relative', }, closeButton: { position: 'absolute', top: 20, right: 20, width: 24, height: 24, justifyContent: 'center', alignItems: 'center', zIndex: 1, }, closeButtonText: { fontSize: 20, color: '#999', }, modalHeader: { alignItems: 'center', paddingTop: 12, paddingBottom: 20, }, modalIndicator: { width: 40, height: 4, backgroundColor: '#E0E0E0', borderRadius: 2, }, modalTitle: { fontSize: 20, fontWeight: '600', color: '#000', textAlign: 'center', marginBottom: 12, }, modalText: { fontSize: 16, color: '#666', textAlign: 'center', marginBottom: 24, lineHeight: 22, }, modalButton: { backgroundColor: '#007a6c', height: 50, borderRadius: 25, justifyContent: 'center', alignItems: 'center', }, modalButtonText: { color: '#fff', fontSize: 16, fontWeight: '600', }, });