From c47d9ad14cb712c32314c19c7421a7af374d12c3 Mon Sep 17 00:00:00 2001 From: MinhNN Date: Sun, 7 Dec 2025 23:09:51 +0700 Subject: [PATCH] =?UTF-8?q?c=E1=BA=ADp=20nh=E1=BA=ADt=20themes=20cho=20tab?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(tabs)/diary.tsx | 36 +++++-- components/diary/DateRangePicker.tsx | 77 +++++++++----- components/diary/FilterButton.tsx | 23 ++-- components/diary/FilterModal.tsx | 86 ++++++++++----- components/diary/ShipDropdown.tsx | 151 ++++++++++----------------- components/diary/StatusDropdown.tsx | 47 ++++----- components/diary/TripCard.tsx | 80 ++++++++------ 7 files changed, 275 insertions(+), 225 deletions(-) diff --git a/app/(tabs)/diary.tsx b/app/(tabs)/diary.tsx index 6de5b7d..9dc8fed 100644 --- a/app/(tabs)/diary.tsx +++ b/app/(tabs)/diary.tsx @@ -16,9 +16,11 @@ import { useThings } from "@/state/use-thing"; import { useTripsList } from "@/state/use-tripslist"; import dayjs from "dayjs"; import { useI18n } from "@/hooks/use-i18n"; +import { useThemeContext } from "@/hooks/use-theme-context"; export default function diary() { const { t } = useI18n(); + const { colors } = useThemeContext(); const [showFilterModal, setShowFilterModal] = useState(false); const [filters, setFilters] = useState({ status: null, @@ -136,11 +138,30 @@ export default function diary() { // TODO: Show confirmation dialog and delete trip }; + // Dynamic styles based on theme + const themedStyles = { + safeArea: { + backgroundColor: colors.background, + }, + titleText: { + color: colors.text, + }, + countText: { + color: colors.textSecondary, + }, + addButton: { + backgroundColor: colors.primary, + }, + emptyText: { + color: colors.textSecondary, + }, + }; + return ( - + {/* Header */} - {t("diary.title")} + {t("diary.title")} {/* Filter & Add Button Row */} @@ -154,7 +175,7 @@ export default function diary() { } /> console.log("Add trip")} activeOpacity={0.7} > @@ -164,7 +185,7 @@ export default function diary() { {/* Trip Count */} - + {t("diary.tripListCount", { count: tripsList?.total || 0 })} @@ -189,7 +210,7 @@ export default function diary() { {(!tripsList || !tripsList.trips || tripsList.trips.length === 0) && ( - + {t("diary.noTripsFound")} @@ -210,7 +231,6 @@ export default function diary() { const styles = StyleSheet.create({ safeArea: { flex: 1, - backgroundColor: "#F9FAFB", }, container: { flex: 1, @@ -221,7 +241,6 @@ const styles = StyleSheet.create({ fontWeight: "700", lineHeight: 36, marginBottom: 10, - color: "#111827", fontFamily: Platform.select({ ios: "System", android: "Roboto", @@ -245,7 +264,6 @@ const styles = StyleSheet.create({ countText: { fontSize: 16, fontWeight: "600", - color: "#374151", fontFamily: Platform.select({ ios: "System", android: "Roboto", @@ -256,7 +274,6 @@ const styles = StyleSheet.create({ addButton: { flexDirection: "row", alignItems: "center", - backgroundColor: "#3B82F6", paddingHorizontal: 16, paddingVertical: 8, borderRadius: 8, @@ -285,7 +302,6 @@ const styles = StyleSheet.create({ }, emptyText: { fontSize: 16, - color: "#9CA3AF", fontFamily: Platform.select({ ios: "System", android: "Roboto", diff --git a/components/diary/DateRangePicker.tsx b/components/diary/DateRangePicker.tsx index 185a849..e552ed6 100644 --- a/components/diary/DateRangePicker.tsx +++ b/components/diary/DateRangePicker.tsx @@ -10,6 +10,7 @@ import { import { Ionicons } from "@expo/vector-icons"; import DateTimePicker from "@react-native-community/datetimepicker"; import { useI18n } from "@/hooks/use-i18n"; +import { useThemeContext } from "@/hooks/use-theme-context"; interface DateRangePickerProps { startDate: Date | null; @@ -25,6 +26,7 @@ export default function DateRangePicker({ onEndDateChange, }: DateRangePickerProps) { const { t } = useI18n(); + const { colors, colorScheme } = useThemeContext(); const [showStartPicker, setShowStartPicker] = useState(false); const [showEndPicker, setShowEndPicker] = useState(false); @@ -50,17 +52,46 @@ export default function DateRangePicker({ } }; + // Dynamic styles based on theme + const themedStyles = { + label: { + color: colors.text, + }, + dateInput: { + backgroundColor: colors.card, + borderColor: colors.border, + }, + dateText: { + color: colors.text, + }, + placeholder: { + color: colors.textSecondary, + }, + pickerContainer: { + backgroundColor: colors.card, + }, + pickerHeader: { + borderBottomColor: colors.border, + }, + pickerTitle: { + color: colors.text, + }, + cancelButton: { + color: colors.textSecondary, + }, + }; + return ( - {t("diary.dateRangePicker.label")} + {t("diary.dateRangePicker.label")} {/* Start Date */} setShowStartPicker(true)} activeOpacity={0.7} > - + {startDate ? formatDate(startDate) : t("diary.dateRangePicker.startDate")} @@ -68,17 +99,17 @@ export default function DateRangePicker({ {/* End Date */} setShowEndPicker(true)} activeOpacity={0.7} > - + {endDate ? formatDate(endDate) : t("diary.dateRangePicker.endDate")} @@ -87,7 +118,7 @@ export default function DateRangePicker({ style={styles.calendarButton} onPress={() => setShowStartPicker(true)} > - + @@ -95,12 +126,12 @@ export default function DateRangePicker({ {showStartPicker && ( - - + + setShowStartPicker(false)}> - {t("common.cancel")} + {t("common.cancel")} - {t("diary.dateRangePicker.selectStartDate")} + {t("diary.dateRangePicker.selectStartDate")} setShowStartPicker(false)}> {t("diary.dateRangePicker.done")} @@ -111,6 +142,8 @@ export default function DateRangePicker({ display={Platform.OS === "ios" ? "spinner" : "default"} onChange={handleStartDateChange} maximumDate={endDate || undefined} + themeVariant={colorScheme} + textColor={colors.text} /> @@ -121,12 +154,12 @@ export default function DateRangePicker({ {showEndPicker && ( - - + + setShowEndPicker(false)}> - {t("common.cancel")} + {t("common.cancel")} - {t("diary.dateRangePicker.selectEndDate")} + {t("diary.dateRangePicker.selectEndDate")} setShowEndPicker(false)}> {t("diary.dateRangePicker.done")} @@ -137,6 +170,8 @@ export default function DateRangePicker({ display={Platform.OS === "ios" ? "spinner" : "default"} onChange={handleEndDateChange} minimumDate={startDate || undefined} + themeVariant={colorScheme} + textColor={colors.text} /> @@ -153,7 +188,6 @@ const styles = StyleSheet.create({ label: { fontSize: 16, fontWeight: "600", - color: "#111827", marginBottom: 8, fontFamily: Platform.select({ ios: "System", @@ -168,25 +202,19 @@ const styles = StyleSheet.create({ }, dateInput: { flex: 1, - backgroundColor: "#FFFFFF", borderWidth: 1, - borderColor: "#D1D5DB", borderRadius: 8, paddingHorizontal: 16, paddingVertical: 12, }, dateText: { fontSize: 16, - color: "#111827", fontFamily: Platform.select({ ios: "System", android: "Roboto", default: "System", }), }, - placeholder: { - color: "#9CA3AF", - }, arrow: { marginHorizontal: 4, }, @@ -199,7 +227,6 @@ const styles = StyleSheet.create({ justifyContent: "flex-end", }, pickerContainer: { - backgroundColor: "#FFFFFF", borderTopLeftRadius: 20, borderTopRightRadius: 20, paddingBottom: 20, @@ -211,12 +238,10 @@ const styles = StyleSheet.create({ paddingHorizontal: 20, paddingVertical: 16, borderBottomWidth: 1, - borderBottomColor: "#F3F4F6", }, pickerTitle: { fontSize: 16, fontWeight: "600", - color: "#111827", fontFamily: Platform.select({ ios: "System", android: "Roboto", @@ -225,7 +250,6 @@ const styles = StyleSheet.create({ }, cancelButton: { fontSize: 16, - color: "#6B7280", fontFamily: Platform.select({ ios: "System", android: "Roboto", @@ -243,3 +267,4 @@ const styles = StyleSheet.create({ }), }, }); + diff --git a/components/diary/FilterButton.tsx b/components/diary/FilterButton.tsx index 79a0eb2..1238b41 100644 --- a/components/diary/FilterButton.tsx +++ b/components/diary/FilterButton.tsx @@ -2,6 +2,7 @@ import React from "react"; import { TouchableOpacity, Text, StyleSheet, Platform } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { useI18n } from "@/hooks/use-i18n"; +import { useThemeContext } from "@/hooks/use-theme-context"; interface FilterButtonProps { onPress?: () => void; @@ -13,26 +14,37 @@ export default function FilterButton({ isFiltered, }: FilterButtonProps) { const { t } = useI18n(); + const { colors } = useThemeContext(); + const themedStyles = { + button: { + backgroundColor: colors.card, + borderColor: colors.border, + }, + text: { + color: isFiltered ? colors.primary : colors.textSecondary, + }, + }; + return ( - + {t("diary.filter")} {isFiltered && ( )} @@ -45,12 +57,10 @@ const styles = StyleSheet.create({ flexDirection: "row", alignItems: "center", justifyContent: "center", - backgroundColor: "#FFFFFF", borderRadius: 12, paddingHorizontal: 20, paddingVertical: 12, borderWidth: 1, - borderColor: "#E5E7EB", shadowColor: "#000", shadowOffset: { width: 0, @@ -63,7 +73,6 @@ const styles = StyleSheet.create({ text: { fontSize: 16, fontWeight: "500", - color: "#374151", marginLeft: 8, fontFamily: Platform.select({ ios: "System", diff --git a/components/diary/FilterModal.tsx b/components/diary/FilterModal.tsx index a1ac3cc..7bc4abd 100644 --- a/components/diary/FilterModal.tsx +++ b/components/diary/FilterModal.tsx @@ -14,6 +14,7 @@ import DateRangePicker from "./DateRangePicker"; import ShipDropdown from "./ShipDropdown"; import { TripStatus } from "./types"; import { useI18n } from "@/hooks/use-i18n"; +import { useThemeContext } from "@/hooks/use-theme-context"; // Map status number to string - now uses i18n export function useMapStatusNumberToString() { @@ -63,6 +64,7 @@ export default function FilterModal({ onApply, }: FilterModalProps) { const { t } = useI18n(); + const { colors } = useThemeContext(); const mapStatusNumberToString = useMapStatusNumberToString(); const [status, setStatus] = useState(null); const [startDate, setStartDate] = useState(null); @@ -87,6 +89,42 @@ export default function FilterModal({ endDate !== null || selectedShip !== null; + const themedStyles = { + modalContainer: { + backgroundColor: colors.card, + }, + header: { + borderBottomColor: colors.separator, + }, + title: { + color: colors.text, + }, + previewContainer: { + backgroundColor: colors.backgroundSecondary, + }, + previewTitle: { + color: colors.textSecondary, + }, + filterTag: { + backgroundColor: colors.primary + '20', // 20% opacity + }, + filterTagText: { + color: colors.primary, + }, + footer: { + borderTopColor: colors.separator, + }, + resetButton: { + backgroundColor: colors.backgroundSecondary, + }, + resetButtonText: { + color: colors.textSecondary, + }, + applyButton: { + backgroundColor: colors.primary, + }, + }; + return ( e.stopPropagation()} > {/* Header */} - + - + - {t("diary.filter")} + {t("diary.filter")} @@ -129,32 +167,32 @@ export default function FilterModal({ {/* Filter Results Preview */} {hasFilters && ( - - {t("diary.selectedFilters")} + + {t("diary.selectedFilters")} {status !== null && ( - - + + {t("diary.statusLabel")} {mapStatusNumberToString(status)} )} {startDate && ( - - + + {t("diary.fromLabel")} {startDate.toLocaleDateString("vi-VN")} )} {endDate && ( - - + + {t("diary.toLabel")} {endDate.toLocaleDateString("vi-VN")} )} {selectedShip && ( - - + + {t("diary.shipLabel")} {selectedShip.shipName} @@ -164,16 +202,16 @@ export default function FilterModal({ {/* Footer */} - + - {t("diary.reset")} + {t("diary.reset")} @@ -186,6 +224,7 @@ export default function FilterModal({ ); } + const styles = StyleSheet.create({ overlay: { flex: 1, @@ -193,7 +232,6 @@ const styles = StyleSheet.create({ justifyContent: "flex-end", }, modalContainer: { - backgroundColor: "#FFFFFF", borderTopLeftRadius: 24, borderTopRightRadius: 24, maxHeight: "80%", @@ -213,7 +251,6 @@ const styles = StyleSheet.create({ paddingHorizontal: 20, paddingVertical: 16, borderBottomWidth: 1, - borderBottomColor: "#F3F4F6", }, closeButton: { padding: 4, @@ -221,7 +258,6 @@ const styles = StyleSheet.create({ title: { fontSize: 18, fontWeight: "700", - color: "#111827", fontFamily: Platform.select({ ios: "System", android: "Roboto", @@ -237,13 +273,11 @@ const styles = StyleSheet.create({ previewContainer: { marginTop: 20, padding: 16, - backgroundColor: "#F9FAFB", borderRadius: 12, }, previewTitle: { fontSize: 14, fontWeight: "600", - color: "#6B7280", marginBottom: 12, fontFamily: Platform.select({ ios: "System", @@ -252,7 +286,6 @@ const styles = StyleSheet.create({ }), }, filterTag: { - backgroundColor: "#EFF6FF", paddingHorizontal: 12, paddingVertical: 6, borderRadius: 16, @@ -261,7 +294,6 @@ const styles = StyleSheet.create({ }, filterTagText: { fontSize: 14, - color: "#3B82F6", fontFamily: Platform.select({ ios: "System", android: "Roboto", @@ -273,11 +305,9 @@ const styles = StyleSheet.create({ gap: 12, padding: 20, borderTopWidth: 1, - borderTopColor: "#F3F4F6", }, resetButton: { flex: 1, - backgroundColor: "#F3F4F6", paddingVertical: 14, borderRadius: 12, alignItems: "center", @@ -285,7 +315,6 @@ const styles = StyleSheet.create({ resetButtonText: { fontSize: 16, fontWeight: "600", - color: "#6B7280", fontFamily: Platform.select({ ios: "System", android: "Roboto", @@ -294,7 +323,6 @@ const styles = StyleSheet.create({ }, applyButton: { flex: 1, - backgroundColor: "#3B82F6", paddingVertical: 14, borderRadius: 12, alignItems: "center", diff --git a/components/diary/ShipDropdown.tsx b/components/diary/ShipDropdown.tsx index dc462db..8948a37 100644 --- a/components/diary/ShipDropdown.tsx +++ b/components/diary/ShipDropdown.tsx @@ -12,6 +12,7 @@ import { import { Ionicons } from "@expo/vector-icons"; import { useThings } from "@/state/use-thing"; import { useI18n } from "@/hooks/use-i18n"; +import { useThemeContext } from "@/hooks/use-theme-context"; interface ShipOption { id: string; @@ -25,6 +26,7 @@ interface ShipDropdownProps { export default function ShipDropdown({ value, onChange }: ShipDropdownProps) { const { t } = useI18n(); + const { colors } = useThemeContext(); const [isOpen, setIsOpen] = useState(false); const [searchText, setSearchText] = useState(""); @@ -53,18 +55,32 @@ export default function ShipDropdown({ value, onChange }: ShipDropdownProps) { const displayValue = value ? value.shipName : t("diary.shipDropdown.placeholder"); + const themedStyles = { + label: { color: colors.text }, + selector: { backgroundColor: colors.card, borderColor: colors.border }, + selectorText: { color: colors.text }, + placeholder: { color: colors.textSecondary }, + modalContent: { backgroundColor: colors.card }, + searchContainer: { backgroundColor: colors.backgroundSecondary, borderColor: colors.border }, + searchInput: { color: colors.text }, + option: { borderBottomColor: colors.separator }, + selectedOption: { backgroundColor: colors.backgroundSecondary }, + optionText: { color: colors.text }, + emptyText: { color: colors.textSecondary }, + }; + return ( - {t("diary.shipDropdown.label")} + {t("diary.shipDropdown.label")} setIsOpen(true)} activeOpacity={0.7} > - + {displayValue} - + setIsOpen(false)} > true} > {/* Search Input */} - + {searchText.length > 0 && ( setSearchText("")}> - + )} - {/* Option to clear selection */} + {/* "All Ships" option */} handleSelect(null)} > - + {t("diary.shipDropdown.allShips")} {!value && ( - + )} - {filteredShips.map((ship) => ( - handleSelect(ship)} - > - - + {/* Filtered ship options */} + {filteredShips.length > 0 ? ( + filteredShips.map((ship) => ( + handleSelect(ship)} + > + {ship.shipName} - - {value?.id === ship.id && ( - - )} - - ))} - - {filteredShips.length === 0 && searchText.length > 0 && ( - - + {value?.id === ship.id && ( + + )} + + )) + ) : ( + + {t("diary.shipDropdown.noShipsFound")} @@ -172,7 +181,6 @@ const styles = StyleSheet.create({ label: { fontSize: 16, fontWeight: "600", - color: "#111827", marginBottom: 8, fontFamily: Platform.select({ ios: "System", @@ -184,16 +192,13 @@ const styles = StyleSheet.create({ flexDirection: "row", justifyContent: "space-between", alignItems: "center", - backgroundColor: "#FFFFFF", borderWidth: 1, - borderColor: "#D1D5DB", borderRadius: 8, paddingHorizontal: 16, paddingVertical: 12, }, selectorText: { fontSize: 16, - color: "#111827", flex: 1, fontFamily: Platform.select({ ios: "System", @@ -201,9 +206,6 @@ const styles = StyleSheet.create({ default: "System", }), }, - placeholder: { - color: "#9CA3AF", - }, modalOverlay: { flex: 1, backgroundColor: "rgba(0, 0, 0, 0.5)", @@ -211,7 +213,6 @@ const styles = StyleSheet.create({ alignItems: "center", }, modalContent: { - backgroundColor: "#FFFFFF", borderRadius: 12, width: "85%", maxHeight: "70%", @@ -231,8 +232,6 @@ const styles = StyleSheet.create({ paddingHorizontal: 16, paddingVertical: 12, borderBottomWidth: 1, - borderBottomColor: "#F3F4F6", - backgroundColor: "#F9FAFB", }, searchIcon: { marginRight: 8, @@ -240,7 +239,6 @@ const styles = StyleSheet.create({ searchInput: { flex: 1, fontSize: 16, - color: "#111827", padding: 0, fontFamily: Platform.select({ ios: "System", @@ -258,58 +256,21 @@ const styles = StyleSheet.create({ paddingHorizontal: 20, paddingVertical: 16, borderBottomWidth: 1, - borderBottomColor: "#F3F4F6", - }, - selectedOption: { - backgroundColor: "#EFF6FF", }, optionText: { fontSize: 16, - color: "#111827", fontFamily: Platform.select({ ios: "System", android: "Roboto", default: "System", }), }, - placeholderOption: { - fontStyle: "italic", - color: "#6B7280", - }, - selectedOptionText: { - color: "#3B82F6", - fontWeight: "600", - }, - shipInfo: { - flex: 1, - }, - shipName: { - fontSize: 16, - color: "#111827", - fontWeight: "500", - marginBottom: 2, - fontFamily: Platform.select({ - ios: "System", - android: "Roboto", - default: "System", - }), - }, - regNumber: { - fontSize: 14, - color: "#6B7280", - fontFamily: Platform.select({ - ios: "System", - android: "Roboto", - default: "System", - }), - }, - emptyState: { + emptyContainer: { paddingVertical: 24, alignItems: "center", }, emptyText: { fontSize: 14, - color: "#9CA3AF", fontFamily: Platform.select({ ios: "System", android: "Roboto", diff --git a/components/diary/StatusDropdown.tsx b/components/diary/StatusDropdown.tsx index 23d332d..2ff7c68 100644 --- a/components/diary/StatusDropdown.tsx +++ b/components/diary/StatusDropdown.tsx @@ -11,6 +11,7 @@ import { import { Ionicons } from "@expo/vector-icons"; import { TripStatus } from "./types"; import { useI18n } from "@/hooks/use-i18n"; +import { useThemeContext } from "@/hooks/use-theme-context"; interface StatusDropdownProps { value: TripStatus | null; @@ -22,6 +23,7 @@ export default function StatusDropdown({ onChange, }: StatusDropdownProps) { const { t } = useI18n(); + const { colors } = useThemeContext(); const [isOpen, setIsOpen] = useState(false); const STATUS_OPTIONS: Array<{ value: TripStatus | null; label: string }> = [ @@ -42,18 +44,29 @@ export default function StatusDropdown({ setIsOpen(false); }; + const themedStyles = { + label: { color: colors.text }, + selector: { backgroundColor: colors.card, borderColor: colors.border }, + selectorText: { color: colors.text }, + placeholder: { color: colors.textSecondary }, + modalContent: { backgroundColor: colors.card }, + option: { borderBottomColor: colors.separator }, + selectedOption: { backgroundColor: colors.backgroundSecondary }, + optionText: { color: colors.text }, + }; + return ( - {t("diary.statusDropdown.label")} + {t("diary.statusDropdown.label")} setIsOpen(true)} activeOpacity={0.7} > - + {selectedLabel} - + setIsOpen(false)} > - + {STATUS_OPTIONS.map((option, index) => ( handleSelect(option.value)} > {option.label} {value === option.value && ( - + )} ))} @@ -106,7 +120,6 @@ const styles = StyleSheet.create({ label: { fontSize: 16, fontWeight: "600", - color: "#111827", marginBottom: 8, fontFamily: Platform.select({ ios: "System", @@ -118,25 +131,19 @@ const styles = StyleSheet.create({ flexDirection: "row", justifyContent: "space-between", alignItems: "center", - backgroundColor: "#FFFFFF", borderWidth: 1, - borderColor: "#D1D5DB", borderRadius: 8, paddingHorizontal: 16, paddingVertical: 12, }, selectorText: { fontSize: 16, - color: "#111827", fontFamily: Platform.select({ ios: "System", android: "Roboto", default: "System", }), }, - placeholder: { - color: "#9CA3AF", - }, modalOverlay: { flex: 1, backgroundColor: "rgba(0, 0, 0, 0.5)", @@ -144,7 +151,6 @@ const styles = StyleSheet.create({ alignItems: "center", }, modalContent: { - backgroundColor: "#FFFFFF", borderRadius: 12, width: "80%", maxHeight: "60%", @@ -165,22 +171,13 @@ const styles = StyleSheet.create({ paddingHorizontal: 20, paddingVertical: 16, borderBottomWidth: 1, - borderBottomColor: "#F3F4F6", - }, - selectedOption: { - backgroundColor: "#EFF6FF", }, optionText: { fontSize: 16, - color: "#111827", fontFamily: Platform.select({ ios: "System", android: "Roboto", default: "System", }), }, - selectedOptionText: { - color: "#3B82F6", - fontWeight: "600", - }, }); diff --git a/components/diary/TripCard.tsx b/components/diary/TripCard.tsx index 139c1c3..eefcd57 100644 --- a/components/diary/TripCard.tsx +++ b/components/diary/TripCard.tsx @@ -11,6 +11,7 @@ import { useTripStatusConfig } from "./types"; import { useThings } from "@/state/use-thing"; import dayjs from "dayjs"; import { useI18n } from "@/hooks/use-i18n"; +import { useThemeContext } from "@/hooks/use-theme-context"; interface TripCardProps { trip: Model.Trip; @@ -32,6 +33,7 @@ export default function TripCard({ onDelete, }: TripCardProps) { const { t } = useI18n(); + const { colors } = useThemeContext(); const { things } = useThings(); const TRIP_STATUS_CONFIG = useTripStatusConfig(); @@ -54,8 +56,30 @@ export default function TripCard({ const showSend = trip.trip_status === 0; const showDelete = trip.trip_status === 1; + const themedStyles = { + card: { + backgroundColor: colors.card, + borderColor: colors.border, + }, + title: { + color: colors.text, + }, + label: { + color: colors.textSecondary, + }, + value: { + color: colors.text, + }, + divider: { + backgroundColor: colors.separator, + }, + actionText: { + color: colors.textSecondary, + }, + }; + return ( - + {/* Header */} @@ -66,7 +90,7 @@ export default function TripCard({ color={statusConfig.textColor} /> - {trip.name} + {trip.name} - {t("diary.tripCard.shipCode")} - + {t("diary.tripCard.shipCode")} + {thingOfTrip?.metadata?.ship_reg_number /* hoặc trip.ship_id */} - {t("diary.tripCard.departure")} - + {t("diary.tripCard.departure")} + {trip.departure_time ? dayjs(trip.departure_time).format("DD/MM/YYYY HH:mm") : "-"} @@ -109,9 +133,9 @@ export default function TripCard({ - {t("diary.tripCard.return")} + {t("diary.tripCard.return")} {/* FIXME: trip.returnDate không có trong dữ liệu API, cần mapping từ trip.arrival_time */} - + {trip.arrival_time ? dayjs(trip.arrival_time).format("DD/MM/YYYY HH:mm") : "-"} @@ -121,15 +145,15 @@ export default function TripCard({ {/* Action Buttons */} - + - - {t("diary.tripCard.view")} + + {t("diary.tripCard.view")} {showEdit && ( @@ -138,8 +162,8 @@ export default function TripCard({ onPress={onEdit} activeOpacity={0.7} > - - {t("diary.tripCard.edit")} + + {t("diary.tripCard.edit")} )} @@ -148,8 +172,8 @@ export default function TripCard({ onPress={onTeam} activeOpacity={0.7} > - - {t("diary.tripCard.team")} + + {t("diary.tripCard.team")} {showSend && ( @@ -158,8 +182,8 @@ export default function TripCard({ onPress={onSend} activeOpacity={0.7} > - - {t("diary.tripCard.send")} + + {t("diary.tripCard.send")} )} @@ -169,7 +193,7 @@ export default function TripCard({ onPress={onDelete} activeOpacity={0.7} > - + {t("diary.tripCard.delete")} )} @@ -180,7 +204,6 @@ export default function TripCard({ const styles = StyleSheet.create({ card: { - backgroundColor: "#FFFFFF", borderRadius: 12, padding: 16, marginBottom: 12, @@ -193,7 +216,6 @@ const styles = StyleSheet.create({ shadowRadius: 8, elevation: 2, borderWidth: 1, - borderColor: "#F3F4F6", }, header: { flexDirection: "row", @@ -213,7 +235,6 @@ const styles = StyleSheet.create({ title: { fontSize: 16, fontWeight: "600", - color: "#111827", marginBottom: 2, fontFamily: Platform.select({ ios: "System", @@ -238,15 +259,15 @@ const styles = StyleSheet.create({ }, infoGrid: { gap: 12, + marginBottom: 12, }, infoRow: { flexDirection: "row", justifyContent: "space-between", - alignItems: "center", + paddingVertical: 8, }, label: { fontSize: 14, - color: "#6B7280", fontFamily: Platform.select({ ios: "System", android: "Roboto", @@ -255,9 +276,7 @@ const styles = StyleSheet.create({ }, value: { fontSize: 14, - color: "#111827", fontWeight: "500", - textAlign: "right", fontFamily: Platform.select({ ios: "System", android: "Roboto", @@ -266,25 +285,20 @@ const styles = StyleSheet.create({ }, divider: { height: 1, - backgroundColor: "#F3F4F6", - marginTop: 16, + marginVertical: 12, }, actionsContainer: { flexDirection: "row", justifyContent: "space-around", - paddingTop: 12, + alignItems: "center", }, actionButton: { flexDirection: "row", alignItems: "center", - gap: 6, - paddingVertical: 8, - paddingHorizontal: 12, + gap: 4, }, actionText: { fontSize: 14, - color: "#6B7280", - fontWeight: "500", fontFamily: Platform.select({ ios: "System", android: "Roboto",