import React, { useState, useEffect } from 'react'; import { View, Text, StyleSheet, FlatList, TouchableOpacity, ActivityIndicator, RefreshControl, } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; import { useRouter } from 'expo-router'; import { Ionicons } from '@expo/vector-icons'; import orderApi, { Order } from '../../services/orderApi'; const STATUS_COLORS: Record = { PENDING: '#FFA726', CONFIRMED: '#42A5F5', SHIPPING: '#AB47BC', DELIVERED: '#66BB6A', CANCELLED: '#EF5350', }; const STATUS_LABELS: Record = { PENDING: 'Chờ xác nhận', CONFIRMED: 'Đã xác nhận', SHIPPING: 'Đang giao', DELIVERED: 'Đã giao', CANCELLED: 'Đã hủy', }; const FILTER_TABS = [ { key: 'ALL', label: 'Tất cả' }, { key: 'PENDING', label: 'Chờ xác nhận' }, { key: 'SHIPPING', label: 'Đang giao' }, { key: 'DELIVERED', label: 'Đã giao' }, { key: 'CANCELLED', label: 'Đã hủy' }, ]; export default function OrdersListScreen() { const router = useRouter(); const [orders, setOrders] = useState([]); const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); const [activeTab, setActiveTab] = useState('ALL'); useEffect(() => { loadOrders(); }, [activeTab]); const loadOrders = async () => { try { const response = activeTab === 'ALL' ? await orderApi.getAllOrders() : await orderApi.getOrdersByStatus(activeTab); if (response.success && response.data) { setOrders(response.data); } } catch (error: any) { console.error('Load orders error:', error); } finally { setLoading(false); setRefreshing(false); } }; const onRefresh = () => { setRefreshing(true); loadOrders(); }; const formatDate = (dateString: string) => { const date = new Date(dateString); return date.toLocaleDateString('vi-VN', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit', }); }; const formatPrice = (price: number) => { return new Intl.NumberFormat('vi-VN', { style: 'currency', currency: 'VND', }).format(price); }; const renderOrderItem = ({ item }: { item: Order }) => ( router.push(`/order-detail?id=${item.orderId}`)} > Đơn hàng #{item.orderId} {STATUS_LABELS[item.orderStatus]} {formatDate(item.createdAt)} {item.orderItems.slice(0, 2).map((orderItem) => ( • {orderItem.productName} x{orderItem.quantity} ))} {item.orderItems.length > 2 && ( và {item.orderItems.length - 2} sản phẩm khác )} Tổng tiền: {formatPrice(item.totalPrice)} Xem chi tiết ); const renderEmptyList = () => ( Chưa có đơn hàng nào router.push('/')} > Mua sắm ngay ); if (loading) { return ( ); } return ( {/* Header */} router.back()}> Đơn hàng của tôi {/* Filter Tabs */} item.key} renderItem={({ item }) => ( setActiveTab(item.key)} > {item.label} )} /> {/* Orders List */} item.orderId.toString()} contentContainerStyle={orders.length > 0 ? styles.listContainer : styles.emptyListContainer} ListEmptyComponent={renderEmptyList} refreshControl={ } /> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#f5f5f5', }, header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', padding: 16, backgroundColor: '#fff', borderBottomWidth: 1, borderBottomColor: '#e0e0e0', }, headerTitle: { fontSize: 20, fontWeight: '700', color: '#333', }, tabContainer: { backgroundColor: '#fff', paddingVertical: 12, borderBottomWidth: 1, borderBottomColor: '#e0e0e0', }, tab: { paddingHorizontal: 16, paddingVertical: 8, marginHorizontal: 4, borderRadius: 20, }, activeTab: { backgroundColor: '#ff6b6b', }, tabText: { fontSize: 14, color: '#666', }, activeTabText: { color: '#fff', fontWeight: '700', }, listContainer: { padding: 12, }, emptyListContainer: { flex: 1, }, orderCard: { backgroundColor: '#fff', borderRadius: 12, padding: 16, marginBottom: 12, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4, elevation: 3, }, orderHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8, }, orderId: { fontSize: 16, fontWeight: '700', color: '#333', }, statusBadge: { paddingHorizontal: 12, paddingVertical: 6, borderRadius: 12, }, statusText: { color: '#fff', fontSize: 12, fontWeight: '700', }, orderDate: { fontSize: 13, color: '#999', marginBottom: 12, }, orderItems: { marginBottom: 12, }, productName: { fontSize: 14, color: '#333', marginBottom: 4, }, moreItems: { fontSize: 13, color: '#666', fontStyle: 'italic', }, orderFooter: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingTop: 12, borderTopWidth: 1, borderTopColor: '#f0f0f0', }, totalLabel: { fontSize: 15, color: '#666', }, totalPrice: { fontSize: 18, fontWeight: '700', color: '#ff6b6b', }, viewDetailButton: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', marginTop: 12, }, viewDetailText: { color: '#ff6b6b', fontSize: 14, fontWeight: '700', marginRight: 4, }, loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, emptyContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', paddingVertical: 60, }, emptyText: { fontSize: 16, color: '#999', marginTop: 16, marginBottom: 24, }, shopButton: { backgroundColor: '#ff6b6b', paddingHorizontal: 32, paddingVertical: 14, borderRadius: 12, }, shopButtonText: { color: '#fff', fontSize: 16, fontWeight: '700', }, });