import React, { useState, useEffect, useRef } from 'react'; import { View, Text, TextInput, TouchableOpacity, FlatList, Image, ActivityIndicator, KeyboardAvoidingView, Platform, Alert, Modal, } from 'react-native'; import { useRoute, useNavigation, RouteProp } from '@react-navigation/native'; import { StackNavigationProp } from '@react-navigation/stack'; import { Header } from '@components'; import { useAppTheme } from '@theme'; import { useCustomerSupport } from '@hooks'; import { getStyles } from './supportChatScreen.styles'; import { AppStackParamList } from '../../../navigation/appStack'; import { formatTime, getFullUrl } from '../../../utils/helper'; type SupportChatRouteProp = RouteProp; type SupportChatNavProp = StackNavigationProp; // Mock attachments that users can select to simulate image attachments const MOCK_ATTACHMENTS = [ { id: 'att1', label: 'Receipt Invoice', url: 'https://images.unsplash.com/photo-1554415707-6e8cfc93fe23?w=500&auto=format&fit=crop&q=60', }, { id: 'att2', label: 'Damaged Packing', url: 'https://images.unsplash.com/photo-1607344645866-009c320c5ab8?w=500&auto=format&fit=crop&q=60', }, { id: 'att3', label: 'Wrong Item Delivered', url: 'https://images.unsplash.com/photo-1546069901-ba9599a7e63c?w=500&auto=format&fit=crop&q=60', }, ]; export const SupportChatScreen: React.FC = () => { const { colors } = useAppTheme(); const styles = getStyles(colors); const route = useRoute(); const navigation = useNavigation(); const { ticketId } = route.params; const { currentTicket, messages, loading, isAgentTyping, fetchTicketDetails, sendMessage, reopenTicket, emitTypingStart, emitTypingStop, } = useCustomerSupport(ticketId); const [inputText, setInputText] = useState(''); const [selectedAttachmentUrl, setSelectedAttachmentUrl] = useState(null); const [attachmentModalVisible, setAttachmentModalVisible] = useState(false); const flatListRef = useRef(null); const typingTimeoutRef = useRef(null); useEffect(() => { if (ticketId) { fetchTicketDetails(ticketId); } }, [ticketId, fetchTicketDetails]); // Auto scroll to bottom when messages change useEffect(() => { if (messages.length > 0) { setTimeout(() => { flatListRef.current?.scrollToEnd({ animated: true }); }, 100); } }, [messages]); const handleSend = async () => { if (!inputText.trim() && !selectedAttachmentUrl) return; try { const textToSend = inputText.trim(); const attachmentsToSend = selectedAttachmentUrl ? [selectedAttachmentUrl] : undefined; setInputText(''); setSelectedAttachmentUrl(null); emitTypingStop(); await sendMessage(ticketId, textToSend, attachmentsToSend); } catch (error) { Alert.alert('Error', 'Failed to send message. Please try again.'); } }; const handleInputChange = (text: string) => { setInputText(text); // Emit typing start and manage typing stop timeout emitTypingStart(); if (typingTimeoutRef.current) { clearTimeout(typingTimeoutRef.current); } typingTimeoutRef.current = setTimeout(() => { emitTypingStop(); }, 2000); }; const handleReopen = async () => { try { await reopenTicket(ticketId); Alert.alert('Success', 'Ticket has been reopened.'); } catch (error) { Alert.alert('Error', 'Failed to reopen ticket.'); } }; const getStatusColor = (status?: string) => { switch (status) { case 'OPEN': return { bg: '#E3F2FD', text: '#1E88E5' }; // Blue case 'IN_PROGRESS': return { bg: '#FFF3E0', text: '#FB8C00' }; // Amber case 'RESOLVED': return { bg: '#E8F5E9', text: '#43A047' }; // Green case 'CLOSED': return { bg: '#ECEFF1', text: '#546E7A' }; // Grey default: return { bg: '#F5F5F5', text: '#9E9E9E' }; } }; const statusStyle = getStatusColor(currentTicket?.status); if (loading && !currentTicket) { return (
navigation.goBack()} /> Loading support ticket... ); } const isClosed = currentTicket?.status === 'RESOLVED' || currentTicket?.status === 'CLOSED'; return (
navigation.goBack()} rightComponent={ currentTicket && ( {currentTicket.status.replace('_', ' ')} ) } /> {currentTicket && ( {currentTicket.subject} ID: #{currentTicket.ticketNumber} | Category: {currentTicket.category.replace('_', ' ')} )} item.id} contentContainerStyle={styles.chatList} renderItem={({ item }) => { const isCustomer = item.sender.roleEnum === 'CUSTOMER'; return ( {!isCustomer && ( {item.sender.name} (Support) )} {item.attachments && item.attachments.map((att: string, idx: number) => ( ))} {item.message.trim() ? ( {item.message} ) : null} {formatTime(item.createdAt)} ); }} onContentSizeChange={() => flatListRef.current?.scrollToEnd({ animated: true })} /> {isAgentTyping && ( Agent is typing... )} {/* Selected attachment preview */} {selectedAttachmentUrl && ( setSelectedAttachmentUrl(null)} > )} {/* Input or Reopen prompt */} {isClosed ? ( This ticket has been resolved or closed. Reopen Ticket ) : ( setAttachmentModalVisible(true)} > 📎 )} {/* Attachment Modal */} setAttachmentModalVisible(false)} > Select Mock Attachment {MOCK_ATTACHMENTS.map((item) => ( { setSelectedAttachmentUrl(item.url); setAttachmentModalVisible(false); }} > 🖼️ {item.label} ))} setAttachmentModalVisible(false)} > Cancel ); }; export default SupportChatScreen;