From f3ad6e02f270061a2bed777f75d52bef2f86a855 Mon Sep 17 00:00:00 2001 From: MinhNN Date: Mon, 3 Nov 2025 19:49:42 +0700 Subject: [PATCH] update NetDetailModal --- components/tripInfo/CrewListTable.tsx | 2 +- components/tripInfo/FishingToolsList.tsx | 2 +- components/tripInfo/NetListTable.tsx | 4 +- components/tripInfo/TripCostTable.tsx | 2 +- components/tripInfo/modal/NetDetailModal.tsx | 515 ------------------ .../modal/NetDetailModal/NetDetailModal.tsx | 238 ++++++++ .../components/CatchSectionHeader.tsx | 20 + .../components/FishCardForm.tsx | 202 +++++++ .../components/FishCardHeader.tsx | 29 + .../components/FishCardList.tsx | 119 ++++ .../components/FishSelectDropdown.tsx | 52 ++ .../NetDetailModal/components/InfoSection.tsx | 93 ++++ .../components/NotesSection.tsx | 20 + .../modal/NetDetailModal/components/index.ts | 7 + .../modal/style/NetDetailModal.styles.ts | 35 +- components/ui/icon-symbol.tsx | 4 +- 16 files changed, 821 insertions(+), 523 deletions(-) delete mode 100644 components/tripInfo/modal/NetDetailModal.tsx create mode 100644 components/tripInfo/modal/NetDetailModal/NetDetailModal.tsx create mode 100644 components/tripInfo/modal/NetDetailModal/components/CatchSectionHeader.tsx create mode 100644 components/tripInfo/modal/NetDetailModal/components/FishCardForm.tsx create mode 100644 components/tripInfo/modal/NetDetailModal/components/FishCardHeader.tsx create mode 100644 components/tripInfo/modal/NetDetailModal/components/FishCardList.tsx create mode 100644 components/tripInfo/modal/NetDetailModal/components/FishSelectDropdown.tsx create mode 100644 components/tripInfo/modal/NetDetailModal/components/InfoSection.tsx create mode 100644 components/tripInfo/modal/NetDetailModal/components/NotesSection.tsx create mode 100644 components/tripInfo/modal/NetDetailModal/components/index.ts 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",