import { View, Text, ScrollView, TouchableOpacity, ActivityIndicator, Alert } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { useLocalSearchParams, router } from 'expo-router'; import { useQuery, useQueryClient } from '@tanstack/react-query'; import { api } from '../../../services/api'; import { useAuthStore } from '../../../stores/authStore'; const TYPE_LABEL: Record = { SUSPEND_CLIENT: 'Suspend Client', REACTIVATE_CLIENT: 'Reactivate Client', ACTIVATE_CLIENT: 'Activate Client', }; const TYPE_COLOR: Record = { SUSPEND_CLIENT: '#DC2626', REACTIVATE_CLIENT: '#059669', ACTIVATE_CLIENT: '#0891B2', }; const TYPE_BG: Record = { SUSPEND_CLIENT: '#FEE2E2', REACTIVATE_CLIENT: '#D1FAE5', ACTIVATE_CLIENT: '#ECFEFF', }; const STATUS_COLOR: Record = { PENDING: '#D97706', DONE: '#059669', CANCELLED: '#6B7280', }; const STATUS_BG: Record = { PENDING: '#FFFBEB', DONE: '#D1FAE5', CANCELLED: '#F1F5F9', }; const COMPLETE_CONFIRM: Record = { SUSPEND_CLIENT: 'This will suspend the client and all their active subscriptions. Continue?', REACTIVATE_CLIENT: 'This will reactivate the client and their suspended subscriptions. Continue?', ACTIVATE_CLIENT: 'This will activate the client account and their pending subscription. Continue?', }; function formatDate(iso: string) { return new Date(iso).toLocaleDateString('en-PH', { month: 'short', day: 'numeric', year: 'numeric', hour: '2-digit', minute: '2-digit', }); } function InfoRow({ label, value, isLast }: { label: string; value?: string | null; isLast?: boolean }) { if (!value) return null; return ( {label} {value} ); } export default function ManualTaskDetailScreen() { const { id } = useLocalSearchParams<{ id: string }>(); const { user } = useAuthStore(); const qc = useQueryClient(); const role = user?.roles?.[0] ?? user?.role ?? ''; const { data: task, isLoading, refetch } = useQuery({ queryKey: ['manual-task', id], queryFn: () => api.get(`/api/v1/manual-tasks/${id}`).then(r => r.data?.data ?? r.data), staleTime: 0, }); const isAdminOrStaff = role === 'ADMIN' || role === 'STAFF'; const isPending = task?.status === 'PENDING'; const isDone = task?.status === 'DONE'; const isCancelled = task?.status === 'CANCELLED'; const handleAssignToMe = async () => { try { const res = await api.patch(`/api/v1/manual-tasks/${id}/assign`, { assignedToId: user?.sub ?? user?.id }); qc.setQueryData(['manual-task', id], (old: any) => ({ ...(old ?? {}), ...res.data })); qc.invalidateQueries({ queryKey: ['manual-tasks'] }); } catch (e: any) { Alert.alert('Error', e?.response?.data?.message ?? 'Could not assign task.'); } }; const handleComplete = () => { const confirmMsg = COMPLETE_CONFIRM[task?.type] ?? 'Complete this task?'; Alert.alert('Complete Task', confirmMsg, [ { text: 'Cancel', style: 'cancel' }, { text: 'Complete', onPress: async () => { try { const res = await api.patch(`/api/v1/manual-tasks/${id}/complete`, { clientId: task?.clientId ?? task?.client?.id }); qc.setQueryData(['manual-task', id], (old: any) => ({ ...(old ?? {}), ...res.data })); qc.invalidateQueries({ queryKey: ['manual-tasks'] }); Alert.alert('Done', 'Task completed successfully.'); } catch (e: any) { Alert.alert('Error', e?.response?.data?.message ?? 'Could not complete task.'); } }, }, ]); }; const handleCancel = () => { Alert.alert('Cancel Task', 'Are you sure you want to cancel this task?', [ { text: 'No', style: 'cancel' }, { text: 'Yes, Cancel', style: 'destructive', onPress: async () => { try { const res = await api.patch(`/api/v1/manual-tasks/${id}/cancel`); qc.setQueryData(['manual-task', id], (old: any) => ({ ...(old ?? {}), ...res.data })); qc.invalidateQueries({ queryKey: ['manual-tasks'] }); } catch (e: any) { Alert.alert('Error', e?.response?.data?.message ?? 'Could not cancel task.'); } }, }, ]); }; if (isLoading) { return ( ); } const typeLabel = TYPE_LABEL[task?.type] ?? task?.type ?? ''; const typeColor = TYPE_COLOR[task?.type] ?? '#6B7280'; const typeBg = TYPE_BG[task?.type] ?? '#F1F5F9'; const statusColor = STATUS_COLOR[task?.status] ?? '#6B7280'; const statusBg = STATUS_BG[task?.status] ?? '#F1F5F9'; const assignedName = task?.assignedTo ? `${task.assignedTo.firstName} ${task.assignedTo.lastName}` : 'Unassigned'; const clientName = task?.client ? `${task.client.firstName} ${task.client.lastName}` : null; return ( {/* Header */} router.back()} style={{ marginBottom: 12 }} activeOpacity={0.7}> โ† Back {/* Type badge (large) */} {typeLabel} {/* Status badge */} {task?.status} {clientName && ( {clientName} ยท {task?.client?.accountNumber} {' ยท '}{assignedName} )} {/* Info Card */} {/* State banners */} {isDone && ( โœ… Task Completed {task?.completedAt && ( {formatDate(task.completedAt)} )} )} {isCancelled && ( ๐Ÿšซ Task Cancelled )} {/* Actions โ€” PENDING + ADMIN/STAFF */} {isPending && isAdminOrStaff && ( {/* Assign to me */} Assign to Me {/* Complete Task */} โœ“ Complete Task {/* Cancel */} Cancel Task )} ); }