update tab nhật ký (Lọc, Ngôn ngữ,...)
This commit is contained in:
@@ -9,22 +9,25 @@ import {
|
||||
} 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";
|
||||
import { useTripsList } from "@/state/use-tripslist";
|
||||
import dayjs from "dayjs";
|
||||
import { useI18n } from "@/hooks/use-i18n";
|
||||
|
||||
export default function diary() {
|
||||
const [searchText, setSearchText] = useState("");
|
||||
const { t } = useI18n();
|
||||
const [showFilterModal, setShowFilterModal] = useState(false);
|
||||
const [filters, setFilters] = useState<FilterValues>({
|
||||
status: null,
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
selectedShip: null, // Tàu được chọn
|
||||
});
|
||||
// Body things (đang fix cứng)
|
||||
|
||||
// Body call API things (đang fix cứng)
|
||||
const payloadThings: Model.SearchThingBody = {
|
||||
offset: 0,
|
||||
limit: 200,
|
||||
@@ -34,56 +37,44 @@ export default function diary() {
|
||||
not_empty: "ship_name, ship_reg_number",
|
||||
},
|
||||
};
|
||||
|
||||
// Gọi API things
|
||||
const { things, getThings } = useThings();
|
||||
const { 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;
|
||||
// State cho payload trips
|
||||
const [payloadTrips, setPayloadTrips] = useState<Model.TripListBody>({
|
||||
name: "",
|
||||
order: "",
|
||||
dir: "desc",
|
||||
offset: 0,
|
||||
limit: 10,
|
||||
metadata: {
|
||||
from: "",
|
||||
to: "",
|
||||
ship_name: "",
|
||||
reg_number: "",
|
||||
province_code: "",
|
||||
owner_id: "",
|
||||
ship_id: "",
|
||||
status: "",
|
||||
},
|
||||
});
|
||||
|
||||
const handleSearch = (text: string) => {
|
||||
setSearchText(text);
|
||||
};
|
||||
const { tripsList, getTripsList } = useTripsList();
|
||||
|
||||
// Gọi API trips lần đầu
|
||||
useEffect(() => {
|
||||
getTripsList(payloadTrips);
|
||||
}, []);
|
||||
|
||||
// Gọi lại API khi payload thay đổi (do filter)
|
||||
useEffect(() => {
|
||||
getTripsList(payloadTrips);
|
||||
console.log("Payload trips:", payloadTrips);
|
||||
}, [payloadTrips]);
|
||||
|
||||
const handleFilter = () => {
|
||||
setShowFilterModal(true);
|
||||
@@ -91,6 +82,28 @@ export default function diary() {
|
||||
|
||||
const handleApplyFilters = (newFilters: FilterValues) => {
|
||||
setFilters(newFilters);
|
||||
|
||||
// Cập nhật payload với filter mới
|
||||
// Lưu ý: status gửi lên server là string
|
||||
const updatedPayload: Model.TripListBody = {
|
||||
...payloadTrips,
|
||||
metadata: {
|
||||
...payloadTrips.metadata,
|
||||
from: newFilters.startDate
|
||||
? dayjs(newFilters.startDate).startOf("day").toISOString()
|
||||
: "",
|
||||
to: newFilters.endDate
|
||||
? dayjs(newFilters.endDate).endOf("day").toISOString()
|
||||
: "",
|
||||
// Convert number status sang string để gửi lên server
|
||||
status: newFilters.status !== null ? String(newFilters.status) : "",
|
||||
// Thêm ship_id từ tàu đã chọn
|
||||
ship_name: newFilters.selectedShip?.shipName || "",
|
||||
},
|
||||
};
|
||||
|
||||
setPayloadTrips(updatedPayload);
|
||||
setShowFilterModal(false);
|
||||
};
|
||||
|
||||
const handleTripPress = (tripId: string) => {
|
||||
@@ -124,39 +137,44 @@ export default function diary() {
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.safeArea}>
|
||||
<SafeAreaView style={styles.safeArea} edges={["top"]}>
|
||||
<View style={styles.container}>
|
||||
{/* Header */}
|
||||
<Text style={styles.titleText}>Nhật ký chuyến đi</Text>
|
||||
<Text style={styles.titleText}>{t("diary.title")}</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>
|
||||
{/* Filter & Add Button Row */}
|
||||
<View style={styles.actionRow}>
|
||||
<FilterButton
|
||||
onPress={handleFilter}
|
||||
isFiltered={
|
||||
filters.status !== null ||
|
||||
filters.startDate !== null ||
|
||||
filters.endDate !== null ||
|
||||
filters.selectedShip !== null
|
||||
}
|
||||
/>
|
||||
<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>
|
||||
<Text style={styles.addButtonText}>{t("diary.addTrip")}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Trip Count */}
|
||||
<Text style={styles.countText}>
|
||||
{t("diary.tripListCount", { count: tripsList?.total || 0 })}
|
||||
</Text>
|
||||
|
||||
{/* Trip List */}
|
||||
<ScrollView
|
||||
style={styles.scrollView}
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
{filteredTrips.map((trip) => (
|
||||
{tripsList?.trips?.map((trip) => (
|
||||
<TripCard
|
||||
key={trip.id}
|
||||
trip={trip}
|
||||
@@ -169,10 +187,10 @@ export default function diary() {
|
||||
/>
|
||||
))}
|
||||
|
||||
{filteredTrips.length === 0 && (
|
||||
{(!tripsList || !tripsList.trips || tripsList.trips.length === 0) && (
|
||||
<View style={styles.emptyState}>
|
||||
<Text style={styles.emptyText}>
|
||||
Không tìm thấy chuyến đi phù hợp
|
||||
{t("diary.noTripsFound")}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
@@ -210,6 +228,13 @@ const styles = StyleSheet.create({
|
||||
default: "System",
|
||||
}),
|
||||
},
|
||||
actionRow: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "flex-start",
|
||||
alignItems: "center",
|
||||
gap: 12,
|
||||
marginBottom: 12,
|
||||
},
|
||||
headerRow: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
@@ -226,6 +251,7 @@ const styles = StyleSheet.create({
|
||||
android: "Roboto",
|
||||
default: "System",
|
||||
}),
|
||||
marginBottom: 10,
|
||||
},
|
||||
addButton: {
|
||||
flexDirection: "row",
|
||||
|
||||
Reference in New Issue
Block a user