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

@@ -7,10 +7,13 @@ import {
Platform,
} from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { Trip, TRIP_STATUS_CONFIG } from "./types";
import { useTripStatusConfig } from "./types";
import { useThings } from "@/state/use-thing";
import dayjs from "dayjs";
import { useI18n } from "@/hooks/use-i18n";
interface TripCardProps {
trip: Trip;
trip: Model.Trip;
onPress?: () => void;
onView?: () => void;
onEdit?: () => void;
@@ -19,13 +22,37 @@ interface TripCardProps {
onDelete?: () => void;
}
export default function TripCard({ trip, onPress, onView, onEdit, onTeam, onSend, onDelete }: TripCardProps) {
const statusConfig = TRIP_STATUS_CONFIG[trip.status];
export default function TripCard({
trip,
onPress,
onView,
onEdit,
onTeam,
onSend,
onDelete,
}: TripCardProps) {
const { t } = useI18n();
const { things } = useThings();
const TRIP_STATUS_CONFIG = useTripStatusConfig();
// Tìm thing có id trùng với vms_id của trip
const thingOfTrip: Model.Thing | undefined = things?.find(
(thing) => thing.id === trip.vms_id
);
// Lấy config status từ trip_status (number)
const statusKey = trip.trip_status as keyof typeof TRIP_STATUS_CONFIG;
const statusConfig = TRIP_STATUS_CONFIG[statusKey] || {
label: "-",
bgColor: "#eee",
textColor: "#333",
icon: "help",
};
// Determine which actions to show based on status
const showEdit = trip.status === 'created' || trip.status === 'pending';
const showSend = trip.status === 'created';
const showDelete = trip.status === 'pending';
const showEdit = trip.trip_status === 0 || trip.trip_status === 1;
const showSend = trip.trip_status === 0;
const showDelete = trip.trip_status === 1;
return (
<View style={styles.card}>
@@ -39,8 +66,7 @@ export default function TripCard({ trip, onPress, onView, onEdit, onTeam, onSend
color={statusConfig.textColor}
/>
<View style={styles.titleContainer}>
<Text style={styles.title}>{trip.title}</Text>
<Text style={styles.code}>{trip.code}</Text>
<Text style={styles.title}>{trip.name}</Text>
</View>
</View>
<View
@@ -67,25 +93,29 @@ export default function TripCard({ trip, onPress, onView, onEdit, onTeam, onSend
{/* Info Grid */}
<View style={styles.infoGrid}>
<View style={styles.infoRow}>
<Text style={styles.label}>Tàu</Text>
<Text style={styles.label}>{t("diary.tripCard.shipCode")}</Text>
<Text style={styles.value}>
{trip.vessel} ({trip.vesselCode})
{thingOfTrip?.metadata?.ship_reg_number /* hoặc trip.ship_id */}
</Text>
</View>
<View style={styles.infoRow}>
<Text style={styles.label}>Khởi hành</Text>
<Text style={styles.value}>{trip.departureDate}</Text>
<Text style={styles.label}>{t("diary.tripCard.departure")}</Text>
<Text style={styles.value}>
{trip.departure_time
? dayjs(trip.departure_time).format("DD/MM/YYYY HH:mm")
: "-"}
</Text>
</View>
<View style={styles.infoRow}>
<Text style={styles.label}>Trở về</Text>
<Text style={styles.value}>{trip.returnDate || "-"}</Text>
</View>
<View style={styles.infoRow}>
<Text style={styles.label}>Thời gian</Text>
<Text style={[styles.value, styles.duration]}>{trip.duration}</Text>
<Text style={styles.label}>{t("diary.tripCard.return")}</Text>
{/* FIXME: trip.returnDate không có trong dữ liệu API, cần mapping từ trip.arrival_time */}
<Text style={styles.value}>
{trip.arrival_time
? dayjs(trip.arrival_time).format("DD/MM/YYYY HH:mm")
: "-"}
</Text>
</View>
</View>
</TouchableOpacity>
@@ -93,34 +123,54 @@ export default function TripCard({ trip, onPress, onView, onEdit, onTeam, onSend
{/* Action Buttons */}
<View style={styles.divider} />
<View style={styles.actionsContainer}>
<TouchableOpacity style={styles.actionButton} onPress={onView} activeOpacity={0.7}>
<TouchableOpacity
style={styles.actionButton}
onPress={onView}
activeOpacity={0.7}
>
<Ionicons name="eye-outline" size={20} color="#6B7280" />
<Text style={styles.actionText}>View</Text>
<Text style={styles.actionText}>{t("diary.tripCard.view")}</Text>
</TouchableOpacity>
{showEdit && (
<TouchableOpacity style={styles.actionButton} onPress={onEdit} activeOpacity={0.7}>
<TouchableOpacity
style={styles.actionButton}
onPress={onEdit}
activeOpacity={0.7}
>
<Ionicons name="create-outline" size={20} color="#6B7280" />
<Text style={styles.actionText}>Edit</Text>
<Text style={styles.actionText}>{t("diary.tripCard.edit")}</Text>
</TouchableOpacity>
)}
<TouchableOpacity style={styles.actionButton} onPress={onTeam} activeOpacity={0.7}>
<TouchableOpacity
style={styles.actionButton}
onPress={onTeam}
activeOpacity={0.7}
>
<Ionicons name="people-outline" size={20} color="#6B7280" />
<Text style={styles.actionText}>Team</Text>
<Text style={styles.actionText}>{t("diary.tripCard.team")}</Text>
</TouchableOpacity>
{showSend && (
<TouchableOpacity style={styles.actionButton} onPress={onSend} activeOpacity={0.7}>
<TouchableOpacity
style={styles.actionButton}
onPress={onSend}
activeOpacity={0.7}
>
<Ionicons name="send-outline" size={20} color="#6B7280" />
<Text style={styles.actionText}>Send</Text>
<Text style={styles.actionText}>{t("diary.tripCard.send")}</Text>
</TouchableOpacity>
)}
{showDelete && (
<TouchableOpacity style={styles.actionButton} onPress={onDelete} activeOpacity={0.7}>
<TouchableOpacity
style={styles.actionButton}
onPress={onDelete}
activeOpacity={0.7}
>
<Ionicons name="trash-outline" size={20} color="#EF4444" />
<Text style={[styles.actionText, styles.deleteText]}>Delete</Text>
<Text style={[styles.actionText, styles.deleteText]}>{t("diary.tripCard.delete")}</Text>
</TouchableOpacity>
)}
</View>
@@ -171,15 +221,7 @@ const styles = StyleSheet.create({
default: "System",
}),
},
code: {
fontSize: 14,
color: "#6B7280",
fontFamily: Platform.select({
ios: "System",
android: "Roboto",
default: "System",
}),
},
badge: {
paddingHorizontal: 12,
paddingVertical: 4,
@@ -222,9 +264,6 @@ const styles = StyleSheet.create({
default: "System",
}),
},
duration: {
color: "#3B82F6",
},
divider: {
height: 1,
backgroundColor: "#F3F4F6",