Files
SeaGateway-App/components/tripInfo/NetListTable.tsx
2025-11-03 19:49:42 +07:00

295 lines
8.1 KiB
TypeScript

import { IconSymbol } from "@/components/ui/icon-symbol";
import React, { useRef, useState } from "react";
import { Animated, Text, TouchableOpacity, View } from "react-native";
import NetDetailModal from "./modal/NetDetailModal/NetDetailModal";
import styles from "./style/NetListTable.styles";
// ---------------------------
// 🧩 Interface
// ---------------------------
interface FishCatch {
fish_species_id: number;
fish_name: string;
catch_number: number;
catch_unit: string;
fish_size: number;
fish_rarity: number;
fish_condition: string;
gear_usage: string;
}
interface NetItem {
id: string;
stt: string;
trangThai: string;
thoiGianBatDau?: string;
thoiGianKetThuc?: string;
viTriHaThu?: string;
viTriThuLuoi?: string;
doSauHaThu?: string;
doSauThuLuoi?: string;
catchList?: FishCatch[];
ghiChu?: string;
}
// ---------------------------
// 🧵 Dữ liệu mẫu
// ---------------------------
const data: NetItem[] = [
{
id: "1",
stt: "Mẻ 3",
trangThai: "Đã hoàn thành",
thoiGianBatDau: "08:00 - 01/11/2025",
thoiGianKetThuc: "12:30 - 01/11/2025",
viTriHaThu: "16°12'34\"N 107°56'12\"E",
viTriThuLuoi: "16°13'45\"N 107°57'23\"E",
doSauHaThu: "45m",
doSauThuLuoi: "48m",
catchList: [
{
fish_species_id: 3,
fish_name: "Cá chim trắng",
catch_number: 978,
catch_unit: "kg",
fish_size: 111,
fish_rarity: 2,
fish_condition: "Chết",
gear_usage: "",
},
{
fish_species_id: 13,
fish_name: "Cá song đỏ",
catch_number: 1061,
catch_unit: "kg",
fish_size: 154,
fish_rarity: 2,
fish_condition: "Còn sống",
gear_usage: "",
},
{
fish_species_id: 15,
fish_name: "Cá hồng",
catch_number: 613,
catch_unit: "kg",
fish_size: 199,
fish_rarity: 2,
fish_condition: "Còn sống",
gear_usage: "",
},
],
ghiChu: "Thời tiết tốt, sản lượng cao",
},
{
id: "2",
stt: "Mẻ 2",
trangThai: "Đã hoàn thành",
thoiGianBatDau: "14:00 - 31/10/2025",
thoiGianKetThuc: "18:45 - 31/10/2025",
viTriHaThu: "16°10'20\"N 107°54'30\"E",
viTriThuLuoi: "16°11'30\"N 107°55'40\"E",
doSauHaThu: "40m",
doSauThuLuoi: "42m",
catchList: [
{
fish_species_id: 2,
fish_name: "Cá nục",
catch_number: 1102,
catch_unit: "kg",
fish_size: 12,
fish_rarity: 1,
fish_condition: "Bị thương",
gear_usage: "",
},
{
fish_species_id: 11,
fish_name: "Cá ngừ đại dương",
catch_number: 828,
catch_unit: "kg",
fish_size: 120,
fish_rarity: 1,
fish_condition: "Chết",
gear_usage: "",
},
],
ghiChu: "Biển động nhẹ",
},
{
id: "3",
stt: "Mẻ 1",
trangThai: "Đã hoàn thành",
thoiGianBatDau: "06:30 - 31/10/2025",
thoiGianKetThuc: "11:00 - 31/10/2025",
viTriHaThu: "16°08'15\"N 107°52'45\"E",
viTriThuLuoi: "16°09'25\"N 107°53'55\"E",
doSauHaThu: "35m",
doSauThuLuoi: "38m",
catchList: [
{
fish_species_id: 6,
fish_name: "Cá mú trắng",
catch_number: 1620,
catch_unit: "kg",
fish_size: 75,
fish_rarity: 2,
fish_condition: "Chết",
gear_usage: "",
},
{
fish_species_id: 8,
fish_name: "Cá hồng phớn",
catch_number: 648,
catch_unit: "kg",
fish_size: 25,
fish_rarity: 3,
fish_condition: "Còn sống",
gear_usage: "Lưới rê",
},
{
fish_species_id: 9,
fish_name: "Cá hổ Napoleon",
catch_number: 1111,
catch_unit: "kg",
fish_size: 86,
fish_rarity: 4,
fish_condition: "Bị thương",
gear_usage: "Lưới rê",
},
{
fish_species_id: 17,
fish_name: "Cá nược",
catch_number: 1081,
catch_unit: "kg",
fish_size: 195,
fish_rarity: 1,
fish_condition: "Chết",
gear_usage: "",
},
{
fish_species_id: 18,
fish_name: "Cá đuối quạt",
catch_number: 1198,
catch_unit: "kg",
fish_size: 21,
fish_rarity: 4,
fish_condition: "Chết",
gear_usage: "Câu tay",
},
],
ghiChu: "Mẻ lưới đầu tiên, sản lượng tốt",
},
];
const NetListTable: React.FC = () => {
const [collapsed, setCollapsed] = useState(true);
const [contentHeight, setContentHeight] = useState<number>(0);
const animatedHeight = useRef(new Animated.Value(0)).current;
const [modalVisible, setModalVisible] = useState(false);
const [selectedNet, setSelectedNet] = useState<NetItem | null>(null);
const tongSoMe = data.length;
const handleToggle = () => {
const toValue = collapsed ? contentHeight : 0;
Animated.timing(animatedHeight, {
toValue,
duration: 300,
useNativeDriver: false,
}).start();
setCollapsed((prev) => !prev);
};
const handleStatusPress = (id: string) => {
const net = data.find((item) => item.id === id);
if (net) {
setSelectedNet(net);
setModalVisible(true);
}
};
return (
<View style={styles.container}>
{/* Header toggle */}
<TouchableOpacity
activeOpacity={0.7}
onPress={handleToggle}
style={styles.headerRow}
>
<Text style={styles.title}>Danh sách mẻ lưới</Text>
{collapsed && <Text style={styles.totalCollapsed}>{tongSoMe}</Text>}
<IconSymbol
name={collapsed ? "chevron.down" : "chevron.up"}
size={16}
color="#000"
/>
</TouchableOpacity>
{/* Nội dung ẩn để đo chiều cao */}
<View
style={{ position: "absolute", opacity: 0, zIndex: -1000 }}
onLayout={(event) => {
const height = event.nativeEvent.layout.height;
if (height > 0 && contentHeight === 0) {
setContentHeight(height);
}
}}
>
{/* Header */}
<View style={[styles.row, styles.tableHeader]}>
<Text style={[styles.sttCell, styles.headerText]}>STT</Text>
<Text style={[styles.cell, styles.headerText]}>Trạng thái</Text>
</View>
{/* Body */}
{data.map((item) => (
<View key={item.id} style={styles.row}>
{/* Cột STT */}
<Text style={styles.sttCell}>{item.stt}</Text>
{/* Cột Trạng thái */}
<View style={[styles.cell, styles.statusContainer]}>
<View style={styles.statusDot} />
<TouchableOpacity onPress={() => handleStatusPress(item.id)}>
<Text style={styles.statusText}>{item.trangThai}</Text>
</TouchableOpacity>
</View>
</View>
))}
</View>
{/* Bảng hiển thị với animation */}
<Animated.View style={{ height: animatedHeight, overflow: "hidden" }}>
{/* Header */}
<View style={[styles.row, styles.tableHeader]}>
<Text style={[styles.sttCell, styles.headerText]}>STT</Text>
<Text style={[styles.cell, styles.headerText]}>Trạng thái</Text>
</View>
{/* Body */}
{data.map((item) => (
<View key={item.id} style={styles.row}>
{/* Cột STT */}
<Text style={styles.sttCell}>{item.stt}</Text>
{/* Cột Trạng thái */}
<View style={[styles.cell, styles.statusContainer]}>
<View style={styles.statusDot} />
<TouchableOpacity onPress={() => handleStatusPress(item.id)}>
<Text style={styles.statusText}>{item.trangThai}</Text>
</TouchableOpacity>
</View>
</View>
))}
</Animated.View>
{/* Modal chi tiết */}
<NetDetailModal
visible={modalVisible}
onClose={() => setModalVisible(false)}
netData={selectedNet}
/>
</View>
);
};
export default NetListTable;