import React, { useState , useEffect } from 'react'; import { View, TouchableOpacity, Alert, TextInput, ActivityIndicator } from 'react-native'; import { AppContainer, MyText, tw, MyFlatList, BottomDialog, BottomDropdown, Checkbox, theme, MyTextInput } from 'common-ui'; import { trpc } from '../../../src/trpc-client'; import { useRouter, useLocalSearchParams } from 'expo-router'; import dayjs from 'dayjs'; import MaterialIcons from '@expo/vector-icons/MaterialIcons'; import { Entypo } from '@expo/vector-icons'; import CancelOrderDialog from '@/components/CancelOrderDialog'; const AdminNotesForm = ({ orderId, existingNotes, onClose, refetch }: { orderId: string; existingNotes?: string | null; onClose: () => void; refetch: () => void }) => { const [notesText, setNotesText] = useState(existingNotes || ''); const updateNotesMutation = trpc.admin.order.updateNotes.useMutation(); return ( Admin Notes { updateNotesMutation.mutate( { orderId: parseInt(orderId), adminNotes: notesText }, { onSuccess: () => { onClose(); Alert.alert('Success', 'Notes updated successfully'); refetch(); }, onError: (error: any) => { Alert.alert('Error', error.message || 'Failed to update notes'); }, } ); }} > Save ); }; interface OrderType { id: number; orderId: string; readableId: number; customerName: string | null; address: string; totalAmount: number; deliveryCharge: number; items: { id?: number; name: string; quantity: number; price: number; amount: number; unit: string; isPackaged?: boolean; isPackageVerified?: boolean; }[]; createdAt: string; deliveryTime: string | null; status: 'pending' | 'delivered' | 'cancelled'; isPackaged: boolean; isDelivered: boolean; isCod: boolean; isFlashDelivery: boolean; couponCode?: string; couponDescription?: string; discountAmount?: number; adminNotes?: string | null; userNotes?: string | null; } const OrderItem = ({ order, refetch }: { order: OrderType; refetch: () => void }) => { const id = order.orderId; const router = useRouter(); const [menuOpen, setMenuOpen] = useState(false); const [itemsDialogOpen, setItemsDialogOpen] = useState(false); const [notesDialogOpen, setNotesDialogOpen] = useState(false); const [cancelDialogOpen, setCancelDialogOpen] = useState(false); const [userNotesDialogOpen, setUserNotesDialogOpen] = useState(false); const [adminNotesDialogOpen, setAdminNotesDialogOpen] = useState(false); const [updatingItems, setUpdatingItems] = useState>(new Set()); const updatePackagedMutation = trpc.admin.order.updatePackaged.useMutation(); const updateDeliveredMutation = trpc.admin.order.updateDelivered.useMutation(); const updateItemPackagingMutation = trpc.admin.order.updateOrderItemPackaging.useMutation(); const handleOrderPress = () => { router.push(`/order-details/${order.orderId}` as any); }; const handleMenuOption = () => { setMenuOpen(false); router.push(`/order-details/${order.orderId}` as any); }; const handleMarkPackaged = (isPackaged: boolean) => { updatePackagedMutation.mutate( { orderId: order.orderId.toString(), isPackaged }, { onSuccess: () => { setMenuOpen(false); refetch(); }, } ); }; const handleMarkDelivered = (isDelivered: boolean) => { updateDeliveredMutation.mutate( { orderId: order.orderId.toString(), isDelivered }, { onSuccess: () => { setMenuOpen(false); refetch(); }, } ); }; const handleItemPackagingToggle = (itemId: number, field: 'isPackaged' | 'isPackageVerified', value: boolean) => { setUpdatingItems(prev => new Set(prev).add(itemId)); updateItemPackagingMutation.mutate( { orderItemId: itemId, [field]: value }, { onSuccess: () => { setUpdatingItems(prev => { const newSet = new Set(prev); newSet.delete(itemId); return newSet; }); refetch(); }, onError: (error: any) => { setUpdatingItems(prev => { const newSet = new Set(prev); newSet.delete(itemId); return newSet; }); Alert.alert("Error", error.message || "Failed to update packaging status"); }, } ); }; const getStatusColor = (status: string) => { switch (status) { case 'delivered': return 'bg-green-100 text-green-800'; case 'cancelled': return 'bg-red-100 text-red-800'; default: return 'bg-yellow-100 text-yellow-800'; } }; if(order.id === 162) console.log({order}) return ( <> {/* Header Section */} {order.customerName || 'Unknown Customer'} #{order.readableId} {order.isFlashDelivery && ( FLASH )} {dayjs(order.createdAt).format('MMM D, h:mm A')} setMenuOpen(true)} style={tw`p-2 -mr-2 -mt-2 rounded-full`} > {/* Main Content */} {/* Status Badges */} {/* {order.status} */} {/* {order.isCod && ( COD )} */} Packaged handleMarkPackaged(!order.isPackaged)} onPress={() => {}} size={18} fillColor={theme.colors.gray500} checkColor="#FFFFFF" /> Delivered handleMarkDelivered(!order.isDelivered)} size={18} fillColor="#10B981" checkColor="#FFFFFF" /> {/* Delivery Info */} Delivery Address {order.address} {order.isFlashDelivery ? "Flash Delivery:" : "Slot:"} {order.isFlashDelivery ? dayjs(order.createdAt).add(30, 'minutes').format('MMM D, h:mm A') : order.deliveryTime ? dayjs(order.deliveryTime).format("ddd, MMM D • h:mm A") : 'Not scheduled'} {order.isFlashDelivery && ( 30-Minute Delivery • High Priority )} {/* Items Summary & Total */} setItemsDialogOpen(true)} style={tw`flex-row items-center py-2 px-3 bg-blue-50 rounded-lg flex-1 mr-3`} > {order.items.length} {order.items.length === 1 ? 'item' : 'items'} {order.isFlashDelivery && ( )} Total: ₹{order.totalAmount} {/* Coupons */} {order.couponCode && ( Applied Coupons {order.couponCode} {order.couponDescription && ( {order.couponDescription} )} {order.discountAmount && ( Discount: ₹{order.discountAmount} )} )} {/* Notes Section */} {order.userNotes && ( setUserNotesDialogOpen(true)} > User Notes )} {order.adminNotes && ( setNotesDialogOpen(true)} > Admin Notes )} {/* Footer / Delivery Charge */} {order.deliveryCharge > 0 && ( Delivery Charge ₹{order.deliveryCharge} )} setMenuOpen(false)}> Order Options {order.isFlashDelivery && ( Flash Delivery Order Deliver within 30 minutes • High Priority )} handleMarkPackaged(!order.isPackaged)} > {order.isPackaged ? 'Mark Not Packaged' : 'Mark Packaged'} {order.isPackaged && ( handleMarkDelivered(!order.isDelivered)} > {order.isDelivered ? 'Mark Not Delivered' : 'Mark Delivered'} )} Order Details { setMenuOpen(false); setNotesDialogOpen(true); }} > Admin Notes {order.status !== 'cancelled' && ( { setMenuOpen(false); setCancelDialogOpen(true); }} > Cancel Order )} setItemsDialogOpen(false)}> Order Items {order.isFlashDelivery && ( FLASH )} Total: ₹{order.totalAmount} {order.items.map((item, idx) => ( {item.quantity} {item.unit} {item.name.length > 30 ? `${item.name.substring(0, 30)}...` : item.name} {item.isPackaged !== undefined && item.isPackageVerified !== undefined && ( <> pkg handleItemPackagingToggle(item.id!, 'isPackaged', !item.isPackaged)} size={18} fillColor={updatingItems.has(item.id!) ? "#F59E0B" : "#10B981"} checkColor="#FFFFFF" /> verf handleItemPackagingToggle(item.id!, 'isPackageVerified', !item.isPackageVerified)} size={18} fillColor={updatingItems.has(item.id!) ? "#F59E0B" : "#10B981"} checkColor="#FFFFFF" /> {updatingItems.has(item.id!) && ( )} )} ))} setNotesDialogOpen(false)}> setNotesDialogOpen(false)} refetch={refetch} /> setCancelDialogOpen(false)} onSuccess={refetch} /> setUserNotesDialogOpen(false)}> User Notes {order.userNotes} setAdminNotesDialogOpen(false)}> Admin Notes {order.adminNotes} ); }; export default function Orders() { const router = useRouter(); const { filter } = useLocalSearchParams<{ filter?: string }>(); const [selectedSlot, setSelectedSlot] = useState(null); const [selectedSlotType, setSelectedSlotType] = useState<'slot' | 'flash' | null>(null); const [packagedFilter, setPackagedFilter] = useState<'all' | 'packaged' | 'not_packaged'>('all'); const [packagedChecked, setPackagedChecked] = useState(false); const [notPackagedChecked, setNotPackagedChecked] = useState(false); const [deliveredFilter, setDeliveredFilter] = useState<'all' | 'delivered' | 'not_delivered'>('all'); const [deliveredChecked, setDeliveredChecked] = useState(false); const [notDeliveredChecked, setNotDeliveredChecked] = useState(false); const [cancellationFilter, setCancellationFilter] = useState<'all' | 'cancelled' | 'not_cancelled'>('all'); const [cancelledChecked, setCancelledChecked] = useState(false); const [notCancelledChecked, setNotCancelledChecked] = useState(false); const [flashDeliveryFilter, setFlashDeliveryFilter] = useState<'all' | 'flash' | 'regular'>('all'); const [flashChecked, setFlashChecked] = useState(false); const [regularChecked, setRegularChecked] = useState(false); const [filterDialogOpen, setFilterDialogOpen] = useState(false); // Handle initial filter from URL params useEffect(() => { if (filter === 'flash') { setSelectedSlotType('flash'); setFlashDeliveryFilter('flash'); setFlashChecked(true); setRegularChecked(false); } }, [filter]); const { data: slotsData } = trpc.admin.slots.getAll.useQuery(); const { data, isLoading, isFetchingNextPage, fetchNextPage, hasNextPage, refetch } = trpc.admin.order.getAll.useInfiniteQuery( { limit: 20, slotId: selectedSlotType === 'slot' ? selectedSlot : null, packagedFilter, deliveredFilter, cancellationFilter, flashDeliveryFilter: selectedSlotType === 'flash' ? 'flash' : flashDeliveryFilter }, { getNextPageParam: (lastPage) => lastPage?.nextCursor, } ); const orders = data?.pages.flatMap(page => page?.orders) || []; if (isLoading) { return ( Loading orders... ); } const slotOptions = [ { label: '⚡ Flash Deliveries', value: 'flash' }, ...(slotsData?.slots?.map(slot => ({ label: dayjs(slot.deliveryTime).format('ddd DD MMM, h:mm a'), value: slot.id.toString(), })) || []) ]; return ( <> item!.orderId} renderItem={({ item }) => item ? : null} onEndReached={() => { if (hasNextPage && !isFetchingNextPage) { fetchNextPage(); } }} onEndReachedThreshold={0.5} onRefresh={() => refetch()} ListHeaderComponent={ <> { if (val === 'flash') { setSelectedSlotType('flash'); setSelectedSlot(null); setFlashDeliveryFilter('flash'); // Reset other filters when switching to flash setPackagedFilter('all'); setPackagedChecked(false); setNotPackagedChecked(false); setDeliveredFilter('all'); setDeliveredChecked(false); setNotDeliveredChecked(false); setCancellationFilter('all'); setCancelledChecked(false); setNotCancelledChecked(false); } else { setSelectedSlotType('slot'); setSelectedSlot(val ? Number(val) : null); setFlashDeliveryFilter('all'); } }} placeholder="All slots" /> setFilterDialogOpen(true)} style={tw`p-2`} > {!isLoading && selectedSlotType && ( {selectedSlotType === 'flash' ? `${orders.length} Flash delivery orders` : `${orders.length} Orders in slot` } )} } ListFooterComponent={ isFetchingNextPage ? ( Loading more... ) : null } /> setFilterDialogOpen(false)}> Packaged Status { const newValue = !packagedChecked; setPackagedChecked(newValue); if (newValue && notPackagedChecked) { setPackagedFilter('all'); } else if (newValue) { setPackagedFilter('packaged'); } else if (notPackagedChecked) { setPackagedFilter('not_packaged'); } else { setPackagedFilter('all'); } }} /> Packaged { const newValue = !notPackagedChecked; setNotPackagedChecked(newValue); if (packagedChecked && newValue) { setPackagedFilter('all'); } else if (newValue) { setPackagedFilter('not_packaged'); } else if (packagedChecked) { setPackagedFilter('packaged'); } else { setPackagedFilter('all'); } }} /> Not Packaged Delivered Status { const newValue = !deliveredChecked; setDeliveredChecked(newValue); if (newValue && notDeliveredChecked) { setDeliveredFilter('all'); } else if (newValue) { setDeliveredFilter('delivered'); } else if (notDeliveredChecked) { setDeliveredFilter('not_delivered'); } else { setDeliveredFilter('all'); } }} /> Delivered { const newValue = !notDeliveredChecked; setNotDeliveredChecked(newValue); if (deliveredChecked && newValue) { setDeliveredFilter('all'); } else if (newValue) { setDeliveredFilter('not_delivered'); } else if (deliveredChecked) { setDeliveredFilter('delivered'); } else { setDeliveredFilter('all'); } }} /> Not Delivered Cancellation Status { const newValue = !cancelledChecked; setCancelledChecked(newValue); if (newValue && notCancelledChecked) { setCancellationFilter('all'); } else if (newValue) { setCancellationFilter('cancelled'); } else if (notCancelledChecked) { setCancellationFilter('not_cancelled'); } else { setCancellationFilter('all'); } }} /> Cancelled { const newValue = !notCancelledChecked; setNotCancelledChecked(newValue); if (cancelledChecked && newValue) { setCancellationFilter('all'); } else if (newValue) { setCancellationFilter('not_cancelled'); } else if (cancelledChecked) { setCancellationFilter('cancelled'); } else { setCancellationFilter('all'); } }} /> Not Cancelled Delivery Type { const newValue = !flashChecked; setFlashChecked(newValue); if (newValue && regularChecked) { setFlashDeliveryFilter('all'); } else if (newValue) { setFlashDeliveryFilter('flash'); } else if (regularChecked) { setFlashDeliveryFilter('regular'); } else { setFlashDeliveryFilter('all'); } }} /> ⚡ Flash Delivery { const newValue = !regularChecked; setRegularChecked(newValue); if (flashChecked && newValue) { setFlashDeliveryFilter('all'); } else if (newValue) { setFlashDeliveryFilter('regular'); } else if (flashChecked) { setFlashDeliveryFilter('flash'); } else { setFlashDeliveryFilter('all'); } }} /> Regular Delivery ); }