import { Image } from 'expo-image'; import React, { forwardRef, useImperativeHandle, useState } from 'react'; import { Modal, ScrollView, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import { Images } from '@/constants/images'; interface BoxItem { boxNumber: number; leftQuantity: number; quantity: number; isCompleted: boolean; } interface BoxPopupProps { onSelect: (item: BoxItem) => void; } export interface BoxPopupRef { open: (list: BoxItem[]) => void; close: () => void; } export const BoxPopup = forwardRef(({ onSelect }, ref) => { const [activeBucket, setActiveBucket] = useState(0); const [list, setList] = useState([]); const [visible, setVisible] = useState(false); useImperativeHandle(ref, () => ({ open: (data: BoxItem[]) => { setList(data); setActiveBucket(0); // Reset to first bucket setVisible(true); }, close: () => setVisible(false), })); const handleSelect = (item: BoxItem) => { onSelect(item); setVisible(false); }; // Bucket logic const BUCKET_SIZE = 100; const buckets = Math.ceil(list.length / BUCKET_SIZE); const displayList = list.slice(activeBucket * BUCKET_SIZE, (activeBucket + 1) * BUCKET_SIZE); return ( setVisible(false)}> {/* 标题区域 */} 选择盒子 setVisible(false)}> × {/* 区间选择器 (仅当数量超过100时显示) */} {buckets > 1 && ( {Array.from({ length: buckets }).map((_, index) => { const start = index * BUCKET_SIZE + 1; const end = Math.min((index + 1) * BUCKET_SIZE, list.length); const isActive = activeBucket === index; return ( setActiveBucket(index)} > {start}~{end} ); })} )} {/* 盒子列表 */} {displayList.map((item, index) => ( handleSelect(item)}> {item.boxNumber}箱 {item.leftQuantity}/{item.quantity} ))} ); }); const styles = StyleSheet.create({ overlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.5)', justifyContent: 'flex-end', }, container: { backgroundColor: '#ffc901', borderTopLeftRadius: 10, borderTopRightRadius: 10, maxHeight: '85%', // Increased slightly paddingBottom: 20, }, titleSection: { position: 'relative', alignItems: 'center', paddingVertical: 15, }, titleBg: { backgroundColor: '#ff8c16', paddingHorizontal: 40, paddingVertical: 10, borderRadius: 20, }, titleText: { color: '#fff', fontSize: 16, fontWeight: 'bold', }, closeBtn: { position: 'absolute', right: 15, top: 10, width: 30, height: 30, justifyContent: 'center', alignItems: 'center', }, closeBtnText: { fontSize: 24, color: '#333', fontWeight: 'bold', }, // Bucket Styles bucketContainer: { marginBottom: 10, height: 40, }, bucketScroll: { paddingHorizontal: 10, }, bucketItem: { paddingHorizontal: 15, paddingVertical: 6, borderRadius: 15, backgroundColor: '#fff', marginRight: 10, borderWidth: 1, borderColor: '#eee', justifyContent: 'center', }, bucketItemActive: { backgroundColor: '#ff8c16', borderColor: '#ff8c16', }, bucketText: { fontSize: 12, color: '#333', fontWeight: '500', }, bucketTextActive: { color: '#fff', fontWeight: 'bold', }, content: { backgroundColor: '#fff', marginHorizontal: 10, borderRadius: 13, borderWidth: 1, borderColor: '#000', flex: 1, // Let it take remaining space }, scrollView: { padding: 10, }, grid: { flexDirection: 'row', flexWrap: 'wrap', paddingBottom: 20, }, item: { width: '25%', alignItems: 'center', marginBottom: 15, }, imgBox: { width: 50, // Slightly smaller to fit better height: 50, }, boxImg: { width: '100%', height: '100%', }, numBadge: { backgroundColor: '#959595', borderRadius: 15, paddingHorizontal: 8, paddingVertical: 2, marginTop: 5, }, numText: { color: '#fff', fontSize: 10, // Smaller font fontWeight: '500', }, remaining: { fontSize: 10, color: '#999', fontWeight: 'bold', marginTop: 3, }, });