295 lines
8.1 KiB
TypeScript
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;
|