Files
sgw-owner-app/app/(tabs)/diary.tsx
2025-12-04 15:54:49 +07:00

270 lines
6.8 KiB
TypeScript

import { useEffect, useState } from "react";
import {
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
} from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { Ionicons } from "@expo/vector-icons";
import SearchBar from "@/components/diary/SearchBar";
import FilterButton from "@/components/diary/FilterButton";
import TripCard from "@/components/diary/TripCard";
import FilterModal, { FilterValues } from "@/components/diary/FilterModal";
import { MOCK_TRIPS } from "@/components/diary/mockData";
import { useThings } from "@/state/use-thing";
export default function diary() {
const [searchText, setSearchText] = useState("");
const [showFilterModal, setShowFilterModal] = useState(false);
const [filters, setFilters] = useState<FilterValues>({
status: null,
startDate: null,
endDate: null,
});
// Body things (đang fix cứng)
const payloadThings: Model.SearchThingBody = {
offset: 0,
limit: 200,
order: "name",
dir: "asc",
metadata: {
not_empty: "ship_name, ship_reg_number",
},
};
// Gọi API things
const { things, getThings } = useThings();
useEffect(() => {
getThings(payloadThings);
}, []);
console.log(things);
// Filter trips based on search text and filters
const filteredTrips = MOCK_TRIPS.filter((trip) => {
// Search filter
if (searchText) {
const searchLower = searchText.toLowerCase();
const matchesSearch =
trip.title.toLowerCase().includes(searchLower) ||
trip.code.toLowerCase().includes(searchLower) ||
trip.vessel.toLowerCase().includes(searchLower) ||
trip.vesselCode.toLowerCase().includes(searchLower);
if (!matchesSearch) return false;
}
// Status filter
if (filters.status && trip.status !== filters.status) {
return false;
}
// Date range filter
if (filters.startDate || filters.endDate) {
const tripDate = new Date(trip.departureDate);
if (filters.startDate && tripDate < filters.startDate) {
return false;
}
if (filters.endDate) {
const endOfDay = new Date(filters.endDate);
endOfDay.setHours(23, 59, 59, 999);
if (tripDate > endOfDay) {
return false;
}
}
}
return true;
});
const handleSearch = (text: string) => {
setSearchText(text);
};
const handleFilter = () => {
setShowFilterModal(true);
};
const handleApplyFilters = (newFilters: FilterValues) => {
setFilters(newFilters);
};
const handleTripPress = (tripId: string) => {
// TODO: Navigate to trip detail
console.log("Trip pressed:", tripId);
};
const handleViewTrip = (tripId: string) => {
console.log("View trip:", tripId);
// TODO: Navigate to trip detail view
};
const handleEditTrip = (tripId: string) => {
console.log("Edit trip:", tripId);
// TODO: Navigate to trip edit screen
};
const handleViewTeam = (tripId: string) => {
console.log("View team:", tripId);
// TODO: Navigate to team management
};
const handleSendTrip = (tripId: string) => {
console.log("Send trip:", tripId);
// TODO: Send trip for approval
};
const handleDeleteTrip = (tripId: string) => {
console.log("Delete trip:", tripId);
// TODO: Show confirmation dialog and delete trip
};
return (
<SafeAreaView style={styles.safeArea}>
<View style={styles.container}>
{/* Header */}
<Text style={styles.titleText}>Nhật chuyến đi</Text>
{/* Search Bar */}
<SearchBar onSearch={handleSearch} style={{ marginBottom: 10 }} />
{/* Filter Button */}
<FilterButton onPress={handleFilter} />
{/* Trip Count & Add Button */}
<View style={styles.headerRow}>
<Text style={styles.countText}>
Danh sách chuyến đi ({filteredTrips.length})
</Text>
<TouchableOpacity
style={styles.addButton}
onPress={() => console.log("Add trip")}
activeOpacity={0.7}
>
<Ionicons name="add" size={20} color="#FFFFFF" />
<Text style={styles.addButtonText}>Thêm chuyến đi</Text>
</TouchableOpacity>
</View>
{/* Trip List */}
<ScrollView
style={styles.scrollView}
contentContainerStyle={styles.scrollContent}
showsVerticalScrollIndicator={false}
>
{filteredTrips.map((trip) => (
<TripCard
key={trip.id}
trip={trip}
onPress={() => handleTripPress(trip.id)}
onView={() => handleViewTrip(trip.id)}
onEdit={() => handleEditTrip(trip.id)}
onTeam={() => handleViewTeam(trip.id)}
onSend={() => handleSendTrip(trip.id)}
onDelete={() => handleDeleteTrip(trip.id)}
/>
))}
{filteredTrips.length === 0 && (
<View style={styles.emptyState}>
<Text style={styles.emptyText}>
Không tìm thấy chuyến đi phù hợp
</Text>
</View>
)}
</ScrollView>
</View>
{/* Filter Modal */}
<FilterModal
visible={showFilterModal}
onClose={() => setShowFilterModal(false)}
onApply={handleApplyFilters}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safeArea: {
flex: 1,
backgroundColor: "#F9FAFB",
},
container: {
flex: 1,
padding: 10,
},
titleText: {
fontSize: 28,
fontWeight: "700",
lineHeight: 36,
marginBottom: 10,
color: "#111827",
fontFamily: Platform.select({
ios: "System",
android: "Roboto",
default: "System",
}),
},
headerRow: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
marginTop: 20,
marginBottom: 12,
},
countText: {
fontSize: 16,
fontWeight: "600",
color: "#374151",
fontFamily: Platform.select({
ios: "System",
android: "Roboto",
default: "System",
}),
},
addButton: {
flexDirection: "row",
alignItems: "center",
backgroundColor: "#3B82F6",
paddingHorizontal: 16,
paddingVertical: 8,
borderRadius: 8,
gap: 6,
},
addButtonText: {
fontSize: 14,
fontWeight: "600",
color: "#FFFFFF",
fontFamily: Platform.select({
ios: "System",
android: "Roboto",
default: "System",
}),
},
scrollView: {
flex: 1,
},
scrollContent: {
paddingBottom: 20,
},
emptyState: {
alignItems: "center",
justifyContent: "center",
paddingVertical: 60,
},
emptyText: {
fontSize: 16,
color: "#9CA3AF",
fontFamily: Platform.select({
ios: "System",
android: "Roboto",
default: "System",
}),
},
});