diff --git a/components/tripInfo/CrewListTable.tsx b/components/tripInfo/CrewListTable.tsx
index 0265420..09f769c 100644
--- a/components/tripInfo/CrewListTable.tsx
+++ b/components/tripInfo/CrewListTable.tsx
@@ -128,7 +128,7 @@ const CrewListTable: React.FC = () => {
{tongThanhVien}
)}
diff --git a/components/tripInfo/FishingToolsList.tsx b/components/tripInfo/FishingToolsList.tsx
index 00fcbde..5e7ec30 100644
--- a/components/tripInfo/FishingToolsList.tsx
+++ b/components/tripInfo/FishingToolsList.tsx
@@ -48,7 +48,7 @@ const FishingToolsTable: React.FC = () => {
Danh sách ngư cụ
{collapsed && {tongSoLuong}}
diff --git a/components/tripInfo/NetListTable.tsx b/components/tripInfo/NetListTable.tsx
index 6795366..d93f54b 100644
--- a/components/tripInfo/NetListTable.tsx
+++ b/components/tripInfo/NetListTable.tsx
@@ -1,7 +1,7 @@
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";
+import NetDetailModal from "./modal/NetDetailModal/NetDetailModal";
import styles from "./style/NetListTable.styles";
// ---------------------------
@@ -217,7 +217,7 @@ const NetListTable: React.FC = () => {
Danh sách mẻ lưới
{collapsed && {tongSoMe}}
diff --git a/components/tripInfo/TripCostTable.tsx b/components/tripInfo/TripCostTable.tsx
index 05e9a90..fa509cd 100644
--- a/components/tripInfo/TripCostTable.tsx
+++ b/components/tripInfo/TripCostTable.tsx
@@ -107,7 +107,7 @@ const TripCostTable: React.FC = () => {
)}
diff --git a/components/tripInfo/modal/NetDetailModal.tsx b/components/tripInfo/modal/NetDetailModal.tsx
deleted file mode 100644
index a2753ce..0000000
--- a/components/tripInfo/modal/NetDetailModal.tsx
+++ /dev/null
@@ -1,515 +0,0 @@
-import { IconSymbol } from "@/components/ui/icon-symbol";
-import React, { useState } from "react";
-import {
- Modal,
- ScrollView,
- Text,
- TextInput,
- TouchableOpacity,
- View,
-} from "react-native";
-import styles from "./style/NetDetailModal.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 NetDetail {
- id: string;
- stt: string;
- trangThai: string;
- thoiGianBatDau?: string;
- thoiGianKetThuc?: string;
- viTriHaThu?: string;
- viTriThuLuoi?: string;
- doSauHaThu?: string;
- doSauThuLuoi?: string;
- catchList?: FishCatch[];
- ghiChu?: string;
-}
-
-interface NetDetailModalProps {
- visible: boolean;
- onClose: () => void;
- netData: NetDetail | null;
-}
-
-// ---------------------------
-// 🧵 Component Modal
-// ---------------------------
-const NetDetailModal: React.FC = ({
- visible,
- onClose,
- netData,
-}) => {
- const [isEditing, setIsEditing] = useState(false);
- const [editableCatchList, setEditableCatchList] = useState([]);
- const [selectedFishIndex, setSelectedFishIndex] = useState(
- null
- );
- const [selectedUnitIndex, setSelectedUnitIndex] = useState(
- null
- );
- const [selectedConditionIndex, setSelectedConditionIndex] = useState<
- number | null
- >(null);
-
- // Khởi tạo dữ liệu khi netData thay đổi
- React.useEffect(() => {
- if (netData?.catchList) {
- setEditableCatchList(netData.catchList);
- }
- }, [netData]);
-
- if (!netData) return null;
-
- const isCompleted = netData.trangThai === "Đã hoàn thành";
-
- // Danh sách tên cá có sẵn
- const fishNameOptions = [
- "Cá chim trắng",
- "Cá song đỏ",
- "Cá hồng",
- "Cá nục",
- "Cá ngừ đại dương",
- "Cá mú trắng",
- "Cá hồng phớn",
- "Cá hổ Napoleon",
- "Cá nược",
- "Cá đuối quạt",
- ];
-
- // Danh sách đơn vị
- const unitOptions = ["kg", "con", "tấn"];
-
- // Danh sách tình trạng
- const conditionOptions = ["Còn sống", "Chết", "Bị thương"];
-
- const handleEdit = () => {
- setIsEditing(!isEditing);
- };
-
- const handleSave = () => {
- setIsEditing(false);
- // TODO: Save data to backend
- console.log("Saved catch list:", editableCatchList);
- };
-
- const handleCancel = () => {
- setIsEditing(false);
- setEditableCatchList(netData.catchList || []);
- };
-
- const updateCatchItem = (
- index: number,
- field: keyof FishCatch,
- value: string | number
- ) => {
- setEditableCatchList((prev) =>
- prev.map((item, i) => {
- if (i === index) {
- const updatedItem = { ...item };
- if (
- field === "catch_number" ||
- field === "fish_size" ||
- field === "fish_rarity"
- ) {
- updatedItem[field] = Number(value) || 0;
- } else {
- updatedItem[field] = value as never;
- }
- return updatedItem;
- }
- return item;
- })
- );
- };
-
- const totalCatch = editableCatchList.reduce(
- (sum, item) => sum + item.catch_number,
- 0
- );
-
- const infoItems = [
- { label: "Số thứ tự", value: netData.stt },
- {
- label: "Trạng thái",
- value: netData.trangThai,
- isStatus: true,
- },
- {
- label: "Thời gian bắt đầu",
- value: netData.thoiGianBatDau || "Chưa cập nhật",
- },
- {
- label: "Thời gian kết thúc",
- value: netData.thoiGianKetThuc || "Chưa cập nhật",
- },
- {
- label: "Vị trí hạ thu",
- value: netData.viTriHaThu || "Chưa cập nhật",
- },
- {
- label: "Vị trí thu lưới",
- value: netData.viTriThuLuoi || "Chưa cập nhật",
- },
- {
- label: "Độ sâu hạ thu",
- value: netData.doSauHaThu || "Chưa cập nhật",
- },
- {
- label: "Độ sâu thu lưới",
- value: netData.doSauThuLuoi || "Chưa cập nhật",
- },
- ];
-
- return (
-
-
- {/* Header */}
-
- Chi tiết mẻ lưới
-
- {isEditing ? (
- <>
-
- Hủy
-
-
- Lưu
-
- >
- ) : (
-
-
-
-
-
- )}
-
-
-
-
-
-
-
-
- {/* Content */}
-
- {/* Thông tin chung */}
-
- {infoItems.map((item, index) => (
-
- {item.label}
- {item.isStatus ? (
-
-
- {item.value}
-
-
- ) : (
- {item.value}
- )}
-
- ))}
-
-
- {/* Danh sách cá bắt được */}
-
- Danh sách cá bắt được
-
- Tổng: {totalCatch.toLocaleString()} kg
-
-
-
- {editableCatchList.map((fish, index) => (
-
- {/* Tên cá - Select */}
-
- Tên cá
- {isEditing ? (
-
-
- setSelectedFishIndex(
- selectedFishIndex === index ? null : index
- )
- }
- >
-
- {fish.fish_name}
-
-
-
- {selectedFishIndex === index && (
-
- {fishNameOptions.map((option, optIndex) => (
- {
- updateCatchItem(index, "fish_name", option);
- setSelectedFishIndex(null);
- }}
- >
- {option}
-
- ))}
-
- )}
-
- ) : (
- {fish.fish_name}
- )}
-
-
- {/* Số lượng & Đơn vị */}
-
-
- Số lượng
- {isEditing ? (
-
- updateCatchItem(index, "catch_number", value)
- }
- keyboardType="numeric"
- placeholder="0"
- />
- ) : (
- {fish.catch_number}
- )}
-
-
- Đơn vị
- {isEditing ? (
-
-
- setSelectedUnitIndex(
- selectedUnitIndex === index ? null : index
- )
- }
- >
-
- {fish.catch_unit}
-
-
-
- {selectedUnitIndex === index && (
-
- {unitOptions.map((option, optIndex) => (
- {
- updateCatchItem(index, "catch_unit", option);
- setSelectedUnitIndex(null);
- }}
- >
- {option}
-
- ))}
-
- )}
-
- ) : (
- {fish.catch_unit}
- )}
-
-
-
- {/* Kích thước & Độ hiếm */}
-
-
- Kích thước (cm)
- {isEditing ? (
-
- updateCatchItem(index, "fish_size", value)
- }
- keyboardType="numeric"
- placeholder="0"
- />
- ) : (
- {fish.fish_size} cm
- )}
-
-
- Độ hiếm
- {isEditing ? (
-
- updateCatchItem(index, "fish_rarity", value)
- }
- keyboardType="numeric"
- placeholder="1-5"
- />
- ) : (
- {fish.fish_rarity}
- )}
-
-
-
- {/* Tình trạng */}
-
- Tình trạng
- {isEditing ? (
-
-
- setSelectedConditionIndex(
- selectedConditionIndex === index ? null : index
- )
- }
- >
-
- {fish.fish_condition}
-
-
-
- {selectedConditionIndex === index && (
-
- {conditionOptions.map((option, optIndex) => (
- {
- updateCatchItem(index, "fish_condition", option);
- setSelectedConditionIndex(null);
- }}
- >
- {option}
-
- ))}
-
- )}
-
- ) : (
- {fish.fish_condition}
- )}
-
-
- {/* Ngư cụ sử dụng */}
-
- Ngư cụ sử dụng
- {isEditing ? (
-
- updateCatchItem(index, "gear_usage", value)
- }
- placeholder="Nhập ngư cụ..."
- />
- ) : (
-
- {fish.gear_usage || "Không có"}
-
- )}
-
-
- ))}
-
- {/* Ghi chú */}
- {netData.ghiChu && (
-
-
- Ghi chú
- {netData.ghiChu}
-
-
- )}
-
-
-
- );
-};
-
-export default NetDetailModal;
diff --git a/components/tripInfo/modal/NetDetailModal/NetDetailModal.tsx b/components/tripInfo/modal/NetDetailModal/NetDetailModal.tsx
new file mode 100644
index 0000000..504e804
--- /dev/null
+++ b/components/tripInfo/modal/NetDetailModal/NetDetailModal.tsx
@@ -0,0 +1,238 @@
+import { IconSymbol } from "@/components/ui/icon-symbol";
+import React, { useState } from "react";
+import { Modal, ScrollView, Text, TouchableOpacity, View } from "react-native";
+import styles from "../style/NetDetailModal.styles";
+import { CatchSectionHeader } from "./components/CatchSectionHeader";
+import { FishCardList } from "./components/FishCardList";
+import { InfoSection } from "./components/InfoSection";
+import { NotesSection } from "./components/NotesSection";
+
+// ---------------------------
+// 🧩 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 NetDetail {
+ id: string;
+ stt: string;
+ trangThai: string;
+ thoiGianBatDau?: string;
+ thoiGianKetThuc?: string;
+ viTriHaThu?: string;
+ viTriThuLuoi?: string;
+ doSauHaThu?: string;
+ doSauThuLuoi?: string;
+ catchList?: FishCatch[];
+ ghiChu?: string;
+}
+
+interface NetDetailModalProps {
+ visible: boolean;
+ onClose: () => void;
+ netData: NetDetail | null;
+}
+
+// ---------------------------
+// 🧵 Component Modal
+// ---------------------------
+const NetDetailModal: React.FC = ({
+ visible,
+ onClose,
+ netData,
+}) => {
+ const [isEditing, setIsEditing] = useState(false);
+ const [editableCatchList, setEditableCatchList] = useState([]);
+ const [selectedFishIndex, setSelectedFishIndex] = useState(
+ null
+ );
+ const [selectedUnitIndex, setSelectedUnitIndex] = useState(
+ null
+ );
+ const [selectedConditionIndex, setSelectedConditionIndex] = useState<
+ number | null
+ >(null);
+ const [expandedFishIndices, setExpandedFishIndices] = useState([]);
+
+ // Khởi tạo dữ liệu khi netData thay đổi
+ React.useEffect(() => {
+ if (netData?.catchList) {
+ setEditableCatchList(netData.catchList);
+ }
+ }, [netData]);
+
+ // Reset state khi modal đóng
+ React.useEffect(() => {
+ if (!visible) {
+ setExpandedFishIndices([]);
+ setSelectedFishIndex(null);
+ setSelectedUnitIndex(null);
+ setSelectedConditionIndex(null);
+ setIsEditing(false);
+ }
+ }, [visible]);
+
+ if (!netData) return null;
+
+ const isCompleted = netData.trangThai === "Đã hoàn thành";
+
+ // Danh sách tên cá có sẵn
+ const fishNameOptions = [
+ "Cá chim trắng",
+ "Cá song đỏ",
+ "Cá hồng",
+ "Cá nục",
+ "Cá ngừ đại dương",
+ "Cá mú trắng",
+ "Cá hồng phớn",
+ "Cá hổ Napoleon",
+ "Cá nược",
+ "Cá đuối quạt",
+ ];
+
+ // Danh sách đơn vị
+ const unitOptions = ["kg", "con", "tấn"];
+
+ // Danh sách tình trạng
+ const conditionOptions = ["Còn sống", "Chết", "Bị thương"];
+
+ const handleEdit = () => {
+ setIsEditing(!isEditing);
+ };
+
+ const handleSave = () => {
+ setIsEditing(false);
+ console.log("Saved catch list:", editableCatchList);
+ };
+
+ const handleCancel = () => {
+ setIsEditing(false);
+ setEditableCatchList(netData.catchList || []);
+ };
+
+ const handleToggleExpanded = (index: number) => {
+ setExpandedFishIndices((prev) =>
+ prev.includes(index) ? prev.filter((i) => i !== index) : [...prev, index]
+ );
+ };
+
+ const updateCatchItem = (
+ index: number,
+ field: keyof FishCatch,
+ value: string | number
+ ) => {
+ setEditableCatchList((prev) =>
+ prev.map((item, i) => {
+ if (i === index) {
+ const updatedItem = { ...item };
+ if (
+ field === "catch_number" ||
+ field === "fish_size" ||
+ field === "fish_rarity"
+ ) {
+ updatedItem[field] = Number(value) || 0;
+ } else {
+ updatedItem[field] = value as never;
+ }
+ return updatedItem;
+ }
+ return item;
+ })
+ );
+ };
+
+ const totalCatch = editableCatchList.reduce(
+ (sum, item) => sum + item.catch_number,
+ 0
+ );
+
+ return (
+
+
+ {/* Header */}
+
+ Chi tiết mẻ lưới
+
+ {isEditing ? (
+ <>
+
+ Hủy
+
+
+ Lưu
+
+ >
+ ) : (
+
+
+
+
+
+ )}
+
+
+
+
+
+
+
+
+ {/* Content */}
+
+ {/* Thông tin chung */}
+
+
+ {/* Danh sách cá bắt được */}
+
+
+ {/* Fish cards */}
+
+
+ {/* Ghi chú */}
+
+
+
+
+ );
+};
+
+export default NetDetailModal;
diff --git a/components/tripInfo/modal/NetDetailModal/components/CatchSectionHeader.tsx b/components/tripInfo/modal/NetDetailModal/components/CatchSectionHeader.tsx
new file mode 100644
index 0000000..b9de124
--- /dev/null
+++ b/components/tripInfo/modal/NetDetailModal/components/CatchSectionHeader.tsx
@@ -0,0 +1,20 @@
+import React from "react";
+import { Text, View } from "react-native";
+import styles from "../../style/NetDetailModal.styles";
+
+interface CatchSectionHeaderProps {
+ totalCatch: number;
+}
+
+export const CatchSectionHeader: React.FC = ({
+ totalCatch,
+}) => {
+ return (
+
+ Danh sách cá bắt được
+
+ Tổng: {totalCatch.toLocaleString()} kg
+
+
+ );
+};
diff --git a/components/tripInfo/modal/NetDetailModal/components/FishCardForm.tsx b/components/tripInfo/modal/NetDetailModal/components/FishCardForm.tsx
new file mode 100644
index 0000000..11fb66d
--- /dev/null
+++ b/components/tripInfo/modal/NetDetailModal/components/FishCardForm.tsx
@@ -0,0 +1,202 @@
+import React from "react";
+import { Text, TextInput, View } from "react-native";
+import styles from "../../style/NetDetailModal.styles";
+import { FishSelectDropdown } from "./FishSelectDropdown";
+
+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 FishCardFormProps {
+ fish: FishCatch;
+ index: number;
+ isEditing: boolean;
+ fishNameOptions: string[];
+ unitOptions: string[];
+ conditionOptions: string[];
+ selectedFishIndex: number | null;
+ selectedUnitIndex: number | null;
+ selectedConditionIndex: number | null;
+ setSelectedFishIndex: (index: number | null) => void;
+ setSelectedUnitIndex: (index: number | null) => void;
+ setSelectedConditionIndex: (index: number | null) => void;
+ onUpdateCatchItem: (
+ index: number,
+ field: keyof FishCatch,
+ value: string | number
+ ) => void;
+}
+
+export const FishCardForm: React.FC = ({
+ fish,
+ index,
+ isEditing,
+ fishNameOptions,
+ unitOptions,
+ conditionOptions,
+ selectedFishIndex,
+ selectedUnitIndex,
+ selectedConditionIndex,
+ setSelectedFishIndex,
+ setSelectedUnitIndex,
+ setSelectedConditionIndex,
+ onUpdateCatchItem,
+}) => {
+ return (
+ <>
+ {/* Tên cá - Select */}
+
+ Tên cá
+ {isEditing ? (
+
+ setSelectedFishIndex(selectedFishIndex === index ? null : index)
+ }
+ onSelect={(value: string) => {
+ onUpdateCatchItem(index, "fish_name", value);
+ setSelectedFishIndex(null);
+ }}
+ zIndex={1000 - index}
+ />
+ ) : (
+ {fish.fish_name}
+ )}
+
+
+ {/* Số lượng & Đơn vị */}
+
+
+ Số lượng
+ {isEditing ? (
+
+ onUpdateCatchItem(index, "catch_number", value)
+ }
+ keyboardType="numeric"
+ placeholder="0"
+ />
+ ) : (
+ {fish.catch_number}
+ )}
+
+
+ Đơn vị
+ {isEditing ? (
+
+ setSelectedUnitIndex(selectedUnitIndex === index ? null : index)
+ }
+ onSelect={(value: string) => {
+ onUpdateCatchItem(index, "catch_unit", value);
+ setSelectedUnitIndex(null);
+ }}
+ zIndex={900 - index}
+ />
+ ) : (
+ {fish.catch_unit}
+ )}
+
+
+
+ {/* Kích thước & Độ hiếm */}
+
+
+ Kích thước (cm)
+ {isEditing ? (
+
+ onUpdateCatchItem(index, "fish_size", value)
+ }
+ keyboardType="numeric"
+ placeholder="0"
+ />
+ ) : (
+ {fish.fish_size} cm
+ )}
+
+
+ Độ hiếm
+ {isEditing ? (
+
+ onUpdateCatchItem(index, "fish_rarity", value)
+ }
+ keyboardType="numeric"
+ placeholder="1-5"
+ />
+ ) : (
+ {fish.fish_rarity}
+ )}
+
+
+
+ {/* Tình trạng */}
+
+ Tình trạng
+ {isEditing ? (
+
+ setSelectedConditionIndex(
+ selectedConditionIndex === index ? null : index
+ )
+ }
+ onSelect={(value: string) => {
+ onUpdateCatchItem(index, "fish_condition", value);
+ setSelectedConditionIndex(null);
+ }}
+ zIndex={800 - index}
+ styleOverride={styles.optionsStatusFishList}
+ />
+ ) : (
+ {fish.fish_condition}
+ )}
+
+
+ {/* Ngư cụ sử dụng */}
+
+ Ngư cụ sử dụng
+ {isEditing ? (
+
+ onUpdateCatchItem(index, "gear_usage", value)
+ }
+ placeholder="Nhập ngư cụ..."
+ />
+ ) : (
+ {fish.gear_usage || "Không có"}
+ )}
+
+ >
+ );
+};
diff --git a/components/tripInfo/modal/NetDetailModal/components/FishCardHeader.tsx b/components/tripInfo/modal/NetDetailModal/components/FishCardHeader.tsx
new file mode 100644
index 0000000..af0d6c9
--- /dev/null
+++ b/components/tripInfo/modal/NetDetailModal/components/FishCardHeader.tsx
@@ -0,0 +1,29 @@
+import React from "react";
+import { Text, View } from "react-native";
+import styles from "../../style/NetDetailModal.styles";
+
+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 FishCardHeaderProps {
+ fish: FishCatch;
+}
+
+export const FishCardHeader: React.FC = ({ fish }) => {
+ return (
+
+ {fish.fish_name}:
+
+ {fish.catch_number} {fish.catch_unit}
+
+
+ );
+};
diff --git a/components/tripInfo/modal/NetDetailModal/components/FishCardList.tsx b/components/tripInfo/modal/NetDetailModal/components/FishCardList.tsx
new file mode 100644
index 0000000..50712fb
--- /dev/null
+++ b/components/tripInfo/modal/NetDetailModal/components/FishCardList.tsx
@@ -0,0 +1,119 @@
+import { IconSymbol } from "@/components/ui/icon-symbol";
+import React from "react";
+import { TouchableOpacity, View } from "react-native";
+import styles from "../../style/NetDetailModal.styles";
+import { FishCardForm } from "./FishCardForm";
+import { FishCardHeader } from "./FishCardHeader";
+
+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 FishCardListProps {
+ catchList: FishCatch[];
+ isEditing: boolean;
+ expandedFishIndex: number[];
+ selectedFishIndex: number | null;
+ selectedUnitIndex: number | null;
+ selectedConditionIndex: number | null;
+ fishNameOptions: string[];
+ unitOptions: string[];
+ conditionOptions: string[];
+ onToggleExpanded: (index: number) => void;
+ onUpdateCatchItem: (
+ index: number,
+ field: keyof FishCatch,
+ value: string | number
+ ) => void;
+ setSelectedFishIndex: (index: number | null) => void;
+ setSelectedUnitIndex: (index: number | null) => void;
+ setSelectedConditionIndex: (index: number | null) => void;
+}
+
+export const FishCardList: React.FC = ({
+ catchList,
+ isEditing,
+ expandedFishIndex,
+ selectedFishIndex,
+ selectedUnitIndex,
+ selectedConditionIndex,
+ fishNameOptions,
+ unitOptions,
+ conditionOptions,
+ onToggleExpanded,
+ onUpdateCatchItem,
+ setSelectedFishIndex,
+ setSelectedUnitIndex,
+ setSelectedConditionIndex,
+}) => {
+ // Chuyển về logic đơn giản, không animation
+ const handleToggleCard = (index: number) => {
+ onToggleExpanded(index);
+ };
+
+ return (
+ <>
+ {catchList.map((fish, index) => (
+
+ {/* Chevron button - always on top */}
+
+ handleToggleCard(index)}
+ style={[styles.chevronIconRight, { zIndex: 9999 }]}
+ hitSlop={{ top: 12, bottom: 12, left: 12, right: 12 }}
+ activeOpacity={0.7}
+ >
+
+
+
+
+ {/* Header - Only visible when collapsed */}
+ {!expandedFishIndex.includes(index) && }
+
+ {/* Form - Only show when expanded */}
+ {expandedFishIndex.includes(index) && (
+
+ )}
+
+ ))}
+ >
+ );
+};
diff --git a/components/tripInfo/modal/NetDetailModal/components/FishSelectDropdown.tsx b/components/tripInfo/modal/NetDetailModal/components/FishSelectDropdown.tsx
new file mode 100644
index 0000000..5327539
--- /dev/null
+++ b/components/tripInfo/modal/NetDetailModal/components/FishSelectDropdown.tsx
@@ -0,0 +1,52 @@
+import { IconSymbol } from "@/components/ui/icon-symbol";
+import React from "react";
+import { ScrollView, Text, TouchableOpacity, View } from "react-native";
+import styles from "../../style/NetDetailModal.styles";
+
+interface FishSelectDropdownProps {
+ options: string[];
+ selectedValue: string;
+ isOpen: boolean;
+ onToggle: () => void;
+ onSelect: (value: string) => void;
+ zIndex: number;
+ styleOverride?: any;
+}
+
+export const FishSelectDropdown: React.FC = ({
+ options,
+ selectedValue,
+ isOpen,
+ onToggle,
+ onSelect,
+ zIndex,
+ styleOverride,
+}) => {
+ const dropdownStyle = styleOverride || styles.optionsList;
+
+ return (
+
+
+ {selectedValue}
+
+
+ {isOpen && (
+
+ {options.map((option, optIndex) => (
+ onSelect(option)}
+ >
+ {option}
+
+ ))}
+
+ )}
+
+ );
+};
diff --git a/components/tripInfo/modal/NetDetailModal/components/InfoSection.tsx b/components/tripInfo/modal/NetDetailModal/components/InfoSection.tsx
new file mode 100644
index 0000000..43da266
--- /dev/null
+++ b/components/tripInfo/modal/NetDetailModal/components/InfoSection.tsx
@@ -0,0 +1,93 @@
+import React from "react";
+import { Text, View } from "react-native";
+import styles from "../../style/NetDetailModal.styles";
+
+interface NetDetail {
+ id: string;
+ stt: string;
+ trangThai: string;
+ thoiGianBatDau?: string;
+ thoiGianKetThuc?: string;
+ viTriHaThu?: string;
+ viTriThuLuoi?: string;
+ doSauHaThu?: string;
+ doSauThuLuoi?: string;
+ catchList?: any[];
+ ghiChu?: string;
+}
+
+interface InfoSectionProps {
+ netData: NetDetail;
+ isCompleted: boolean;
+}
+
+export const InfoSection: React.FC = ({
+ netData,
+ isCompleted,
+}) => {
+ const infoItems = [
+ { label: "Số thứ tự", value: netData.stt },
+ {
+ label: "Trạng thái",
+ value: netData.trangThai,
+ isStatus: true,
+ },
+ {
+ label: "Thời gian bắt đầu",
+ value: netData.thoiGianBatDau || "Chưa cập nhật",
+ },
+ {
+ label: "Thời gian kết thúc",
+ value: netData.thoiGianKetThuc || "Chưa cập nhật",
+ },
+ {
+ label: "Vị trí hạ thu",
+ value: netData.viTriHaThu || "Chưa cập nhật",
+ },
+ {
+ label: "Vị trí thu lưới",
+ value: netData.viTriThuLuoi || "Chưa cập nhật",
+ },
+ {
+ label: "Độ sâu hạ thu",
+ value: netData.doSauHaThu || "Chưa cập nhật",
+ },
+ {
+ label: "Độ sâu thu lưới",
+ value: netData.doSauThuLuoi || "Chưa cập nhật",
+ },
+ ];
+
+ return (
+
+ {infoItems.map((item, index) => (
+
+ {item.label}
+ {item.isStatus ? (
+
+
+ {item.value}
+
+
+ ) : (
+ {item.value}
+ )}
+
+ ))}
+
+ );
+};
diff --git a/components/tripInfo/modal/NetDetailModal/components/NotesSection.tsx b/components/tripInfo/modal/NetDetailModal/components/NotesSection.tsx
new file mode 100644
index 0000000..81fa00a
--- /dev/null
+++ b/components/tripInfo/modal/NetDetailModal/components/NotesSection.tsx
@@ -0,0 +1,20 @@
+import React from "react";
+import { Text, View } from "react-native";
+import styles from "../../style/NetDetailModal.styles";
+
+interface NotesSectionProps {
+ ghiChu?: string;
+}
+
+export const NotesSection: React.FC = ({ ghiChu }) => {
+ if (!ghiChu) return null;
+
+ return (
+
+
+ Ghi chú
+ {ghiChu}
+
+
+ );
+};
diff --git a/components/tripInfo/modal/NetDetailModal/components/index.ts b/components/tripInfo/modal/NetDetailModal/components/index.ts
new file mode 100644
index 0000000..f81f198
--- /dev/null
+++ b/components/tripInfo/modal/NetDetailModal/components/index.ts
@@ -0,0 +1,7 @@
+export { CatchSectionHeader } from "./CatchSectionHeader";
+export { FishCardForm } from "./FishCardForm";
+export { FishCardHeader } from "./FishCardHeader";
+export { FishCardList } from "./FishCardList";
+export { FishSelectDropdown } from "./FishSelectDropdown";
+export { InfoSection } from "./InfoSection";
+export { NotesSection } from "./NotesSection";
diff --git a/components/tripInfo/modal/style/NetDetailModal.styles.ts b/components/tripInfo/modal/style/NetDetailModal.styles.ts
index 90d48ee..98a73e5 100644
--- a/components/tripInfo/modal/style/NetDetailModal.styles.ts
+++ b/components/tripInfo/modal/style/NetDetailModal.styles.ts
@@ -140,6 +140,7 @@ const styles = StyleSheet.create({
color: "#007AFF",
},
fishCard: {
+ position: "relative",
backgroundColor: "#fff",
borderRadius: 12,
padding: 16,
@@ -152,7 +153,7 @@ const styles = StyleSheet.create({
},
fieldGroup: {
marginBottom: 12,
- position: "relative",
+ marginTop: 0,
},
rowGroup: {
flexDirection: "row",
@@ -231,6 +232,38 @@ const styles = StyleSheet.create({
shadowRadius: 8,
shadowOffset: { width: 0, height: 4 },
},
+ fishCardHeaderContent: {
+ flexDirection: "row",
+ gap: 5,
+ },
+ chevronIconRight: {
+ position: "absolute",
+ top: 6,
+ right: 12,
+ zIndex: 1000,
+ backgroundColor: "#007AFF",
+ borderRadius: 8,
+ width: 40,
+ height: 40,
+ padding: 0,
+ justifyContent: "center",
+ alignItems: "center",
+ shadowColor: "#000",
+ shadowOpacity: 0.08,
+ shadowRadius: 2,
+ shadowOffset: { width: 0, height: 1 },
+ elevation: 2,
+ },
+ fishCardTitle: {
+ fontSize: 16,
+ fontWeight: "600",
+ color: "#000",
+ },
+ fishCardSubtitle: {
+ fontSize: 15,
+ color: "#ff6600",
+ marginTop: 0,
+ },
});
export default styles;
diff --git a/components/ui/icon-symbol.tsx b/components/ui/icon-symbol.tsx
index c014d69..fa59933 100644
--- a/components/ui/icon-symbol.tsx
+++ b/components/ui/icon-symbol.tsx
@@ -23,8 +23,8 @@ const MAPPING = {
"chevron.right": "chevron-right",
"ferry.fill": "directions-boat",
"map.fill": "map",
- "arrowshape.down.fill": "arrow-drop-down",
- "arrowshape.up.fill": "arrow-drop-up",
+ "chevron.down": "arrow-drop-down",
+ "chevron.up": "arrow-drop-up",
"exclamationmark.triangle.fill": "warning",
"book.closed.fill": "book",
"dot.radiowaves.left.and.right": "sensors",