update netDetail

This commit is contained in:
2025-11-07 11:54:16 +07:00
parent b9cd637b33
commit 25b9e831d1
6 changed files with 93 additions and 17 deletions

View File

@@ -1,6 +1,7 @@
import { IconSymbol } from "@/components/ui/icon-symbol"; import { IconSymbol } from "@/components/ui/icon-symbol";
import { useFishes } from "@/state/use-fish";
import { useTrip } from "@/state/use-trip"; import { useTrip } from "@/state/use-trip";
import React, { useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import { Animated, Text, TouchableOpacity, View } from "react-native"; import { Animated, Text, TouchableOpacity, View } from "react-native";
import NetDetailModal from "./modal/NetDetailModal/NetDetailModal"; import NetDetailModal from "./modal/NetDetailModal/NetDetailModal";
import styles from "./style/NetListTable.styles"; import styles from "./style/NetListTable.styles";
@@ -12,6 +13,10 @@ const NetListTable: React.FC = () => {
const [modalVisible, setModalVisible] = useState(false); const [modalVisible, setModalVisible] = useState(false);
const [selectedNet, setSelectedNet] = useState<Model.FishingLog | null>(null); const [selectedNet, setSelectedNet] = useState<Model.FishingLog | null>(null);
const { trip } = useTrip(); const { trip } = useTrip();
const { fishSpecies, getFishSpecies } = useFishes();
useEffect(() => {
getFishSpecies();
}, []);
const data: Model.FishingLog[] = trip?.fishing_logs ?? []; const data: Model.FishingLog[] = trip?.fishing_logs ?? [];
const tongSoMe = data.length; const tongSoMe = data.length;

View File

@@ -1,3 +1,4 @@
import { useFishes } from "@/state/use-fish";
import React from "react"; import React from "react";
import { Text, TextInput, View } from "react-native"; import { Text, TextInput, View } from "react-native";
import styles from "../../style/NetDetailModal.styles"; import styles from "../../style/NetDetailModal.styles";
@@ -7,8 +8,8 @@ interface FishCardFormProps {
fish: Model.FishingLogInfo; fish: Model.FishingLogInfo;
index: number; index: number;
isEditing: boolean; isEditing: boolean;
fishNameOptions: string[]; fishNameOptions: string[]; // Bỏ gọi API cá
unitOptions: string[]; unitOptions: string[]; // Bỏ render ở trong này
// conditionOptions: string[]; // conditionOptions: string[];
// gearOptions: string[]; // gearOptions: string[];
selectedFishIndex: number | null; selectedFishIndex: number | null;
@@ -30,7 +31,6 @@ export const FishCardForm: React.FC<FishCardFormProps> = ({
fish, fish,
index, index,
isEditing, isEditing,
fishNameOptions,
unitOptions, unitOptions,
// conditionOptions, // conditionOptions,
// gearOptions, // gearOptions,
@@ -44,6 +44,18 @@ export const FishCardForm: React.FC<FishCardFormProps> = ({
// setSelectedGearIndex, // setSelectedGearIndex,
onUpdateCatchItem, onUpdateCatchItem,
}) => { }) => {
const { fishSpecies } = useFishes();
const [fishNameOptions, setFishNameOptions] = React.useState<string[]>([]);
React.useEffect(() => {
console.log("Length: ", fishSpecies?.length);
if (Array.isArray(fishSpecies)) {
const names = fishSpecies.map((item) => item.name).filter(Boolean);
setFishNameOptions(names);
}
}, [fishSpecies]);
return ( return (
<> <>
{/* Tên cá - Select */} {/* Tên cá - Select */}
@@ -53,15 +65,17 @@ export const FishCardForm: React.FC<FishCardFormProps> = ({
<Text style={styles.label}>Tên </Text> <Text style={styles.label}>Tên </Text>
{isEditing ? ( {isEditing ? (
<FishSelectDropdown <FishSelectDropdown
options={fishNameOptions} options={fishSpecies || []}
selectedValue={fish.fish_name ?? ""} selectedValue={null}
isOpen={selectedFishIndex === index} isOpen={selectedFishIndex === index}
onToggle={() => onToggle={() =>
setSelectedFishIndex(selectedFishIndex === index ? null : index) setSelectedFishIndex(selectedFishIndex === index ? null : index)
} }
onSelect={(value: string) => { onSelect={(value: Model.FishSpeciesResponse) => {
onUpdateCatchItem(index, "fish_name", value); onUpdateCatchItem(index, "fish_name", value.name);
setSelectedFishIndex(null); // setSelectedFishIndex(null);
console.log("Fish Selected: ", fish);
}} }}
zIndex={1000 - index} zIndex={1000 - index}
styleOverride={styles.fishNameDropdown} styleOverride={styles.fishNameDropdown}
@@ -96,7 +110,7 @@ export const FishCardForm: React.FC<FishCardFormProps> = ({
]} ]}
> >
<Text style={styles.label}>Đơn vị</Text> <Text style={styles.label}>Đơn vị</Text>
{isEditing ? ( {/* {isEditing ? (
<FishSelectDropdown <FishSelectDropdown
options={unitOptions} options={unitOptions}
selectedValue={fish.catch_unit ?? ""} selectedValue={fish.catch_unit ?? ""}
@@ -112,7 +126,7 @@ export const FishCardForm: React.FC<FishCardFormProps> = ({
/> />
) : ( ) : (
<Text style={styles.infoValue}>{fish.catch_unit}</Text> <Text style={styles.infoValue}>{fish.catch_unit}</Text>
)} )} */}
</View> </View>
</View> </View>

View File

@@ -4,11 +4,11 @@ import { ScrollView, Text, TouchableOpacity, View } from "react-native";
import styles from "../../style/NetDetailModal.styles"; import styles from "../../style/NetDetailModal.styles";
interface FishSelectDropdownProps { interface FishSelectDropdownProps {
options: string[]; options: Model.FishSpeciesResponse[];
selectedValue: string; selectedValue: Model.FishSpeciesResponse | null;
isOpen: boolean; isOpen: boolean;
onToggle: () => void; onToggle: () => void;
onSelect: (value: string) => void; onSelect: (value: Model.FishSpeciesResponse) => void;
zIndex: number; zIndex: number;
styleOverride?: any; styleOverride?: any;
} }
@@ -27,7 +27,9 @@ export const FishSelectDropdown: React.FC<FishSelectDropdownProps> = ({
return ( return (
<View style={{ zIndex }}> <View style={{ zIndex }}>
<TouchableOpacity style={styles.selectButton} onPress={onToggle}> <TouchableOpacity style={styles.selectButton} onPress={onToggle}>
<Text style={styles.selectButtonText}>{selectedValue}</Text> <Text style={styles.selectButtonText}>
{selectedValue ? selectedValue.name : "Chọn cá"}
</Text>
<IconSymbol <IconSymbol
name={isOpen ? "chevron.up" : "chevron.down"} name={isOpen ? "chevron.up" : "chevron.down"}
size={16} size={16}
@@ -38,11 +40,11 @@ export const FishSelectDropdown: React.FC<FishSelectDropdownProps> = ({
<ScrollView style={dropdownStyle} nestedScrollEnabled={true}> <ScrollView style={dropdownStyle} nestedScrollEnabled={true}>
{options.map((option, optIndex) => ( {options.map((option, optIndex) => (
<TouchableOpacity <TouchableOpacity
key={optIndex} key={option.id || optIndex}
style={styles.optionItem} style={styles.optionItem}
onPress={() => onSelect(option)} onPress={() => onSelect(option)}
> >
<Text style={styles.optionText}>{option}</Text> <Text style={styles.optionText}>{option.name}</Text>
</TouchableOpacity> </TouchableOpacity>
))} ))}
</ScrollView> </ScrollView>

View File

@@ -0,0 +1,6 @@
import { api } from "@/config";
import { API_GET_FISH } from "@/constants";
export async function queryFish() {
return api.get<Model.FishSpeciesResponse[]>(API_GET_FISH);
}

View File

@@ -186,4 +186,27 @@ declare namespace Model {
status: number; status: number;
note?: string; note?: string;
} }
//Fish
interface FishSpeciesResponse {
id: number;
name: string;
scientific_name: string;
group_name: string;
species_code: string;
note: string;
default_unit: string;
rarity_level: number;
created_at: string;
updated_at: string;
is_deleted: boolean;
}
interface FishRarity {
id: number;
code: string;
label: string;
description: string;
iucn_code: any;
cites_appendix: any;
vn_law: boolean;
}
} }

26
state/use-fish.ts Normal file
View File

@@ -0,0 +1,26 @@
import { queryFish } from "@/controller/FishController";
import { create } from "zustand";
type Fish = {
fishSpecies: Model.FishSpeciesResponse | null;
getFishSpecies: () => Promise<void>;
error: string | null;
loading?: boolean;
};
export const useFishes = create<Fish>((set) => ({
fishSpecies: null,
getFishSpecies: async () => {
try {
const response = await queryFish();
console.log("Fish fetching API");
set({ fishSpecies: response.data, loading: false });
} catch (error) {
console.error("Error when fetch fish: ", error);
set({ error: "Failed to fetch fish data", loading: false });
set({ fishSpecies: null });
}
},
error: null,
}));