import React, { useState } from 'react'; import { View, TouchableOpacity, Alert, FlatList } from 'react-native'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import { MyText, tw, MyTouchableOpacity, MyFlatList, BottomDialog } from 'common-ui'; import { trpc } from '../../../src/trpc-client'; import dayjs from 'dayjs'; import { LinearGradient } from 'expo-linear-gradient'; interface SlotItemProps { item: any; selectedSlots: number[]; toggleSlotSelection: (slotId: number) => void; setDialogProducts: React.Dispatch>; setDialogOpen: React.Dispatch>; } const SlotItemComponent: React.FC = ({ item: slot, selectedSlots, toggleSlotSelection, setDialogProducts, setDialogOpen, }) => { const isSelected = selectedSlots.includes(slot.id); const slotProducts = slot.products?.map((p: any) => p.name).filter(Boolean) || []; const displayProducts = slotProducts.slice(0, 2).join(', '); const isActive = slot.isActive; const statusColor = isActive ? 'bg-green-100 text-green-700' : 'bg-red-100 text-red-700'; const statusText = isActive ? 'Active' : 'Inactive'; return ( toggleSlotSelection(slot.id)} activeOpacity={0.7} style={tw`bg-white p-5 mb-4 rounded-3xl shadow-sm border border-gray-100`} > {/* Header: Checkbox, ID and Status */} toggleSlotSelection(slot.id)} style={tw`mr-3`}> Slot #{slot.id} ID: {slot.id} {statusText} {/* Divider */} {/* Details Grid */} {/* Delivery Time */} Delivery {dayjs(slot.deliveryTime).format('DD MMM, h:mm A')} {/* Freeze Time */} Freeze {dayjs(slot.freezeTime).format('DD MMM, h:mm A')} {/* Products */} {slotProducts.length > 0 ? ( Products {displayProducts} {slotProducts.length > 2 && ( { setDialogProducts(slotProducts); setDialogOpen(true); }} > +{slotProducts.length - 2} more )} ) : null} ); }; export default function RebalanceOrders() { const [selectedSlots, setSelectedSlots] = useState([]); const [dialogOpen, setDialogOpen] = useState(false); const [dialogProducts, setDialogProducts] = useState([]); const [refreshing, setRefreshing] = useState(false); const { data: slotsData, isLoading, refetch: refetchSlots } = trpc.admin.slots.getAll.useQuery(); const upcomingSlots = slotsData?.slots?.filter(slot => dayjs(slot.deliveryTime).isAfter(dayjs())) || []; const handleRefresh = async () => { setRefreshing(true); await refetchSlots(); setRefreshing(false); }; const { mutate: rebalanceSlots } = trpc.admin.order.rebalanceSlots.useMutation({ onSuccess: () => { refetchSlots(); }, onSettled: () => { Alert.alert("Rebalance Complete", "Slots have been rebalanced."); } }); const toggleSlotSelection = (slotId: number) => { setSelectedSlots(prev => prev.includes(slotId) ? prev.filter(id => id !== slotId) : [...prev, slotId] ); }; const handleRebalance = () => { Alert.alert("Rebalancing...", "Please wait while we rebalance the selected slots.", [{ text: "OK" }]); rebalanceSlots({ slotIds: selectedSlots }); }; if (isLoading) { return ( Loading slots... ); } return ( Rebalance Upcoming Slots {upcomingSlots.length === 0 ? ( No upcoming slots available for rebalancing. ) : ( item.id.toString()} renderItem={({ item }) => ( )} contentContainerStyle={tw`pb-24 flex-1`} // Space for floating button showsVerticalScrollIndicator={false} onRefresh={handleRefresh} refreshing={refreshing} /> )} {/* Floating Rebalance Button */} {/* Products Dialog */} setDialogOpen(false)}> All Products index.toString()} renderItem={({ item }) => ( {item} )} showsVerticalScrollIndicator={false} style={tw`max-h-80`} /> ); }