215 lines
5.4 KiB
TypeScript
215 lines
5.4 KiB
TypeScript
import { 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";
|
|
|
|
export default function diary() {
|
|
const [searchText, setSearchText] = useState("");
|
|
const [showFilterModal, setShowFilterModal] = useState(false);
|
|
const [filters, setFilters] = useState<FilterValues>({
|
|
status: null,
|
|
startDate: null,
|
|
endDate: null,
|
|
});
|
|
|
|
// 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);
|
|
};
|
|
|
|
return (
|
|
<SafeAreaView style={styles.safeArea}>
|
|
<View style={styles.container}>
|
|
{/* Header */}
|
|
<Text style={styles.titleText}>Nhật ký 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)}
|
|
/>
|
|
))}
|
|
|
|
{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: 16,
|
|
},
|
|
titleText: {
|
|
fontSize: 28,
|
|
fontWeight: "700",
|
|
lineHeight: 36,
|
|
marginBottom: 20,
|
|
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",
|
|
}),
|
|
},
|
|
});
|