freshyo/apps/admin-ui/components/SnippetOrdersView.tsx
2026-01-24 00:13:15 +05:30

158 lines
No EOL
5.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react';
import { View, ScrollView, TouchableOpacity } from 'react-native';
import { MyText, tw, AppContainer } from 'common-ui';
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
interface OrderProduct {
productId: number;
productName: string;
quantity: number;
price: number;
unit: string;
subtotal: number;
}
interface SnippetOrder {
orderId: string;
orderDate: string;
customerName: string;
totalAmount: string;
slotInfo: {
time: string;
sequence: any[];
} | null;
products: OrderProduct[];
matchedProducts: number[];
snippetCode: string;
}
interface SnippetOrdersViewProps {
orders: SnippetOrder[];
snippetCode: string;
onClose: () => void;
}
const OrderCard: React.FC<{ order: SnippetOrder; index: number }> = ({ order, index }) => {
const orderDate = new Date(order.orderDate);
const slotTime = order.slotInfo ? new Date(order.slotInfo.time) : null;
return (
<View style={tw`py-6`}>
{/* Order Header */}
<View style={tw`flex-row justify-between items-start mb-3`}>
<View style={tw`flex-1`}>
<MyText style={tw`font-bold text-gray-800 text-lg`}>{order.orderId}</MyText>
<MyText style={tw`text-sm text-gray-600`}>{order.customerName}</MyText>
</View>
<View style={tw`items-end`}>
<MyText style={tw`font-bold text-green-600`}>{order.totalAmount}</MyText>
<MyText style={tw`text-xs text-gray-500`}>
{orderDate.toLocaleDateString()}
</MyText>
</View>
</View>
{/* Slot Info */}
{slotTime && (
<View style={tw`mb-3 p-2 bg-blue-50 rounded-lg`}>
<MyText style={tw`text-sm text-blue-800 font-medium`}>
Delivery: {slotTime.toLocaleString()}
</MyText>
</View>
)}
{/* Products */}
<View style={tw`mb-3`}>
<MyText style={tw`text-sm font-semibold text-gray-700 mb-2`}>Products:</MyText>
{order.products.map((product, index) => {
const isMatched = order.matchedProducts.includes(product.productId);
return (
<View
key={index}
style={tw`flex-row justify-between items-center py-1 ${isMatched ? 'bg-yellow-50 px-2 rounded' : ''}`}
>
<View style={tw`flex-1`}>
<MyText style={tw`text-sm ${isMatched ? 'font-semibold text-yellow-800' : 'text-gray-700'}`}>
{product.productName}
{isMatched && ' ⭐'}
</MyText>
<MyText style={tw`text-xs text-gray-500`}>
{product.quantity} {product.unit} × {product.price}
</MyText>
</View>
<MyText style={tw`text-sm font-medium ${isMatched ? 'text-yellow-800' : 'text-gray-700'}`}>
{product.subtotal.toFixed(2)}
</MyText>
</View>
);
})}
</View>
{/* Matched Products Summary */}
<View style={tw`p-2 bg-yellow-50 rounded-lg`}>
<MyText style={tw`text-xs text-yellow-700`}>
Matched {order.matchedProducts.length} product(s) from snippet "{order.snippetCode}"
</MyText>
</View>
</View>
);
};
const SnippetOrdersView: React.FC<SnippetOrdersViewProps> = ({
orders,
snippetCode,
onClose,
}) => {
const totalOrders = orders.length;
const totalRevenue = orders.reduce((sum, order) => sum + parseFloat(order.totalAmount), 0);
return (
<AppContainer>
<View style={tw`flex-1 bg-gray-50`}>
{/* Header */}
<View style={tw`px-6 py-4 bg-white border-b border-gray-200`}>
<View style={tw`flex-row justify-between items-center`}>
<View style={tw`flex-1`}>
<MyText style={tw`text-xl font-bold text-gray-800`}>Orders for "{snippetCode}"</MyText>
<MyText style={tw`text-gray-600 mt-1`}>
{totalOrders} order{totalOrders !== 1 ? 's' : ''} Total: {totalRevenue.toFixed(2)}
</MyText>
</View>
<TouchableOpacity
onPress={onClose}
style={tw`p-2`}
>
<MyText style={tw`text-gray-500 text-lg`}></MyText>
</TouchableOpacity>
</View>
</View>
{/* Orders List */}
<ScrollView style={tw`flex-1 px-6`} showsVerticalScrollIndicator={false}>
{orders.length === 0 ? (
<View style={tw`flex-1 justify-center items-center py-12`}>
<MaterialIcons name="shopping-cart" size={64} color="#D1D5DB" />
<MyText style={tw`text-gray-500 text-lg font-semibold mt-4`}>No matching orders</MyText>
<MyText style={tw`text-gray-400 text-center mt-2`}>
No orders found that match this snippet's criteria
</MyText>
</View>
) : (
<View style={tw`py-4`}>
{orders.map((order, index) => (
<React.Fragment key={index}>
<OrderCard order={order} index={index} />
{index < orders.length - 1 && (
<View style={tw`h-px bg-slate-200 w-full`} />
)}
</React.Fragment>
))}
</View>
)}
</ScrollView>
</View>
</AppContainer>
);
};
export default SnippetOrdersView;