import { useState } from 'react'; import { View, Text, FlatList, TextInput, TouchableOpacity, ActivityIndicator, RefreshControl, ScrollView } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { useQuery } from '@tanstack/react-query'; import { useFocusEffect } from 'expo-router'; import { useCallback } from 'react'; import { router } from 'expo-router'; import { api } from '../../../services/api'; const PRIORITY_COLOR: Record = { HIGH: '#DC2626', NORMAL: '#0891B2', LOW: '#6B7280' }; const PRIORITY_BG: Record = { HIGH: '#FEE2E2', NORMAL: '#ECFEFF', LOW: '#F1F5F9' }; const STATUS_COLOR: Record = { OPEN: '#0891B2', IN_PROGRESS: '#D97706', RESOLVED: '#16A34A', CLOSED: '#6B7280' }; const STATUS_BG: Record = { OPEN: '#ECFEFF', IN_PROGRESS: '#FFFBEB', RESOLVED: '#F0FDF4', CLOSED: '#F1F5F9' }; const TYPE_COLOR: Record = { INSTALLATION: '#0891B2', SUPPORT: '#7C3AED', BILLING: '#D97706' }; const TYPE_BG: Record = { INSTALLATION: '#ECFEFF', SUPPORT: '#F5F3FF', BILLING: '#FFFBEB' }; const STATUS_FILTERS = ['All', 'OPEN', 'IN_PROGRESS', 'RESOLVED', 'CLOSED']; export default function TasksScreen() { const [search, setSearch] = useState(''); const [statusFilter, setStatusFilter] = useState('All'); const { data, isLoading, refetch, isRefetching } = useQuery({ queryKey: ['tasks'], queryFn: () => api.get('/api/v1/tickets?limit=100').then(r => r.data?.data ?? r.data ?? []), }); // Refetch list every time this screen comes into focus (fixes stale list after navigating back) useFocusEffect(useCallback(() => { refetch(); }, [])); const tasks = (data ?? []).filter((t: any) => { const matchSearch = `${t.subject} ${t.client?.firstName ?? ''} ${t.client?.lastName ?? ''}`.toLowerCase().includes(search.toLowerCase()); const matchStatus = statusFilter === 'All' || t.status === statusFilter; return matchSearch && matchStatus; }); return ( Tickets {tasks.length} showing router.push('/(app)/tasks/new')} activeOpacity={0.7} > + Ticket {search.length > 0 && ( setSearch('')} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}> × )} {STATUS_FILTERS.map(f => { const isActive = statusFilter === f; const color = f === 'All' ? '#0891B2' : STATUS_COLOR[f] ?? '#6B7280'; return ( setStatusFilter(f)} style={{ borderRadius: 20, paddingHorizontal: 16, paddingVertical: 8, marginRight: 8, backgroundColor: isActive ? color : '#F1F5F9' }} activeOpacity={0.7} > {f === 'All' ? 'All' : f.replace('_', ' ')} ); })} {isLoading ? ( ) : ( item.id} refreshControl={} contentContainerStyle={{ padding: 16, paddingBottom: 32 }} renderItem={({ item }) => { const typeColor = TYPE_COLOR[item.type] ?? '#6B7280'; const typeBg = TYPE_BG[item.type] ?? '#F1F5F9'; return ( router.push(`/(app)/tasks/${item.id}`)} activeOpacity={0.7} > {item.type} {item.priority === 'HIGH' && ( HIGH )} {item.status?.replace('_', ' ')} {item.subject} {item.client?.firstName} {item.client?.lastName} {item.assignedTo ? ` · ${item.assignedTo.firstName} ${item.assignedTo.lastName}` : ' · Unassigned'} {item._count?.messages > 0 && ( {item._count.messages} message{item._count.messages !== 1 ? 's' : ''} )} ); }} ListEmptyComponent={ No tasks found } /> )} ); }