import React, { useEffect, useState, useMemo } from "react"; import { View, Text, StyleSheet, Platform, TouchableOpacity, ScrollView, ActivityIndicator, } from "react-native"; import { SafeAreaView } from "react-native-safe-area-context"; import { useLocalSearchParams, useRouter } from "expo-router"; import { Ionicons } from "@expo/vector-icons"; import { useI18n } from "@/hooks/use-i18n"; import { useThemeContext } from "@/hooks/use-theme-context"; import { TRIP_STATUS_CONFIG } from "@/components/diary/types"; import { convertFishingGears, convertTripCosts, } from "@/utils/tripDataConverters"; import { queryAlarms } from "@/controller/AlarmController"; import { queryTripCrew } from "@/controller/TripCrewController"; import { queryTripById } from "@/controller/TripController"; // Reuse existing components import CrewList from "@/components/diary/TripCrewModal/CrewList"; import FishingGearList from "@/components/diary/TripFormModal/FishingGearList"; import MaterialCostList from "@/components/diary/TripFormModal/MaterialCostList"; // Section components import { SectionCard, AlertsSection, FishingLogsSection, BasicInfoSection, } from "@/components/diary/TripDetailSections"; export default function TripDetailPage() { const { t } = useI18n(); const { colors } = useThemeContext(); const router = useRouter(); const { tripId } = useLocalSearchParams<{ tripId: string; }>(); const [loading, setLoading] = useState(true); const [trip, setTrip] = useState(null); const [alerts, setAlerts] = useState([]); const [crews, setCrews] = useState([]); // Fetch trip data từ API useEffect(() => { const fetchTripData = async () => { if (!tripId) return; setLoading(true); try { const response = await queryTripById(tripId); if (response.data) { setTrip(response.data); } } catch (error) { console.error("Lỗi khi tải thông tin chuyến đi:", error); } finally { setLoading(false); } }; fetchTripData(); }, [tripId]); // Fetch alarms cho chuyến đi dựa trên thing_id (vms_id) useEffect(() => { const fetchAlarms = async () => { if (!trip?.vms_id) return; try { const response = await queryAlarms({ offset: 0, limit: 100, order: "time", dir: "desc", thing_id: trip.vms_id, }); if (response.data?.alarms) { setAlerts(response.data.alarms); } } catch (error) { console.error("Lỗi khi tải alarms:", error); } }; fetchAlarms(); }, [trip?.vms_id]); // Fetch danh sách thuyền viên useEffect(() => { const fetchCrews = async () => { if (!tripId) return; try { const response = await queryTripCrew(tripId); // API trả về { trip_crews: [...] } if (response.data?.trip_crews) { setCrews(response.data.trip_crews); } } catch (error) {} }; fetchCrews(); }, [tripId]); // Convert trip data to component format using memoization const fishingGears = useMemo( () => convertFishingGears(trip?.fishing_gears, "view"), [trip?.fishing_gears] ); const tripCosts = useMemo( () => convertTripCosts(trip?.trip_cost, "view"), [trip?.trip_cost] ); const statusConfig = useMemo(() => { const status = trip?.trip_status ?? 0; return ( TRIP_STATUS_CONFIG[status as keyof typeof TRIP_STATUS_CONFIG] || TRIP_STATUS_CONFIG[0] ); }, [trip?.trip_status]); // Empty section component const EmptySection = ({ icon, message, }: { icon: string; message: string; }) => ( {message} ); // Render loading state if (loading) { return ( {t("common.loading")} ); } // Render error state if (!trip) { return (
router.back()} colors={colors} /> {t("diary.tripDetail.notFound")} ); } return ( {/* Header with status badge */} router.back()} style={styles.backButton} > {trip.name || t("diary.tripDetail.title")} {statusConfig.label} {/* Content */} {/* Basic Info */} {/* Alerts */} {/* Trip Costs */} {tripCosts.length > 0 ? ( {}} disabled hideTitle /> ) : ( )} {/* Fishing Gears */} {fishingGears.length > 0 ? ( {}} disabled hideTitle /> ) : ( )} {/* Crew List */} {crews.length > 0 ? ( ) : ( )} {/* Fishing Logs */} ); } // Header component for reuse function Header({ title, onBack, colors, }: { title: string; onBack: () => void; colors: any; }) { return ( {title} ); } const styles = StyleSheet.create({ container: { flex: 1, }, loadingContainer: { flex: 1, justifyContent: "center", alignItems: "center", gap: 12, }, loadingText: { fontSize: 14, fontFamily: Platform.select({ ios: "System", android: "Roboto", default: "System", }), }, header: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 16, paddingVertical: 12, borderBottomWidth: 1, }, backButton: { padding: 4, }, headerTitles: { flex: 1, alignItems: "center", gap: 6, }, title: { fontSize: 18, fontWeight: "700", fontFamily: Platform.select({ ios: "System", android: "Roboto", default: "System", }), }, statusBadge: { flexDirection: "row", alignItems: "center", gap: 4, paddingHorizontal: 10, paddingVertical: 4, borderRadius: 12, }, statusText: { fontSize: 11, fontWeight: "600", fontFamily: Platform.select({ ios: "System", android: "Roboto", default: "System", }), }, placeholder: { width: 32, }, content: { flex: 1, }, contentContainer: { padding: 16, paddingBottom: 40, }, errorContainer: { flex: 1, justifyContent: "center", alignItems: "center", gap: 12, paddingHorizontal: 20, }, errorText: { fontSize: 14, textAlign: "center", fontFamily: Platform.select({ ios: "System", android: "Roboto", default: "System", }), }, sectionInnerContent: { marginTop: 5, }, emptySection: { alignItems: "center", justifyContent: "center", paddingVertical: 24, gap: 8, }, emptyText: { fontSize: 14, fontFamily: Platform.select({ ios: "System", android: "Roboto", default: "System", }), }, });