update tab nhật ký (Lọc, Ngôn ngữ,...)

This commit is contained in:
2025-12-07 20:23:10 +07:00
parent 0672f8adf9
commit e405a0bcfa
17 changed files with 851 additions and 332 deletions

View File

@@ -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 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",