fix themes modal, Add English to the trip information tab

This commit is contained in:
2025-11-21 18:46:51 +07:00
parent 6975358a7f
commit 554289ee1e
12 changed files with 148 additions and 82 deletions

View File

@@ -5,17 +5,19 @@ import CrewListTable from "@/components/tripInfo/CrewListTable";
import FishingToolsTable from "@/components/tripInfo/FishingToolsList"; import FishingToolsTable from "@/components/tripInfo/FishingToolsList";
import NetListTable from "@/components/tripInfo/NetListTable"; import NetListTable from "@/components/tripInfo/NetListTable";
import TripCostTable from "@/components/tripInfo/TripCostTable"; import TripCostTable from "@/components/tripInfo/TripCostTable";
import { useI18n } from "@/hooks/use-i18n";
import { useThemeContext } from "@/hooks/use-theme-context"; import { useThemeContext } from "@/hooks/use-theme-context";
import { Platform, ScrollView, StyleSheet, Text, View } from "react-native"; import { Platform, ScrollView, StyleSheet, Text, View } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context"; import { SafeAreaView } from "react-native-safe-area-context";
export default function TripInfoScreen() { export default function TripInfoScreen() {
const { t } = useI18n();
const { colors } = useThemeContext(); const { colors } = useThemeContext();
return ( return (
<SafeAreaView style={styles.safeArea} edges={["top", "left", "right"]}> <SafeAreaView style={styles.safeArea} edges={["top", "left", "right"]}>
<View style={styles.header}> <View style={styles.header}>
<Text style={[styles.titleText, { color: colors.text }]}> <Text style={[styles.titleText, { color: colors.text }]}>
Thông Tin Chuyến Đi {t("trip.infoTrip")}
</Text> </Text>
<View style={styles.buttonWrapper}> <View style={styles.buttonWrapper}>
<ButtonCreateNewHaulOrTrip /> <ButtonCreateNewHaulOrTrip />

View File

@@ -12,6 +12,7 @@ import { useI18n } from "@/hooks/use-i18n";
import { import {
ColorScheme as ThemeColorScheme, ColorScheme as ThemeColorScheme,
useTheme, useTheme,
useThemeContext,
} from "@/hooks/use-theme-context"; } from "@/hooks/use-theme-context";
import { showErrorToast, showWarningToast } from "@/services/toast_service"; import { showErrorToast, showWarningToast } from "@/services/toast_service";
import { import {
@@ -44,6 +45,7 @@ export default function LoginScreen() {
const [isShowingQRScanner, setIsShowingQRScanner] = useState(false); const [isShowingQRScanner, setIsShowingQRScanner] = useState(false);
const { t, setLocale, locale } = useI18n(); const { t, setLocale, locale } = useI18n();
const { colors, colorScheme } = useTheme(); const { colors, colorScheme } = useTheme();
const { setThemeMode } = useThemeContext();
const styles = useMemo( const styles = useMemo(
() => createStyles(colors, colorScheme), () => createStyles(colors, colorScheme),
[colors, colorScheme] [colors, colorScheme]
@@ -312,6 +314,10 @@ export default function LoginScreen() {
inactiveBackgroundColor={colors.surface} inactiveBackgroundColor={colors.surface}
inactiveOverlayColor={colors.textSecondary} inactiveOverlayColor={colors.textSecondary}
activeOverlayColor={colors.background} activeOverlayColor={colors.background}
value={colorScheme === "light"}
onChange={(val) => {
setThemeMode(val ? "light" : "dark");
}}
/> />
</View> </View>

View File

@@ -1,3 +1,4 @@
import { useThemeContext } from "@/hooks/use-theme-context";
import { AntDesign } from "@expo/vector-icons"; import { AntDesign } from "@expo/vector-icons";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { import {
@@ -93,6 +94,12 @@ const Select: React.FC<SelectProps> = ({
const sz = sizeMap[size]; const sz = sizeMap[size];
// Theme colors from context (consistent with other components)
const { colors } = useThemeContext();
const selectBackgroundColor = disabled
? colors.backgroundSecondary
: colors.surface;
return ( return (
<View style={styles.wrapper}> <View style={styles.wrapper}>
<TouchableOpacity <TouchableOpacity
@@ -101,7 +108,8 @@ const Select: React.FC<SelectProps> = ({
{ {
height: sz.height, height: sz.height,
paddingHorizontal: sz.paddingHorizontal, paddingHorizontal: sz.paddingHorizontal,
opacity: disabled ? 0.6 : 1, backgroundColor: selectBackgroundColor,
borderColor: disabled ? colors.border : colors.primary,
}, },
style, style,
]} ]}
@@ -112,14 +120,18 @@ const Select: React.FC<SelectProps> = ({
> >
<View style={styles.content}> <View style={styles.content}>
{loading ? ( {loading ? (
<ActivityIndicator size="small" color="#4ecdc4" /> <ActivityIndicator size="small" color={colors.primary} />
) : ( ) : (
<Text <Text
style={[ style={[
styles.text, styles.text,
{ {
fontSize: sz.fontSize, fontSize: sz.fontSize,
color: selectedValue ? "#111" : "#999", color: disabled
? colors.textSecondary
: selectedValue
? colors.text
: colors.textSecondary,
}, },
]} ]}
numberOfLines={1} numberOfLines={1}
@@ -131,24 +143,41 @@ const Select: React.FC<SelectProps> = ({
<View style={styles.suffix}> <View style={styles.suffix}>
{allowClear && selectedValue && !loading ? ( {allowClear && selectedValue && !loading ? (
<TouchableOpacity onPress={handleClear} style={styles.icon}> <TouchableOpacity onPress={handleClear} style={styles.icon}>
<AntDesign name="close" size={16} color="#999" /> <AntDesign name="close" size={16} color={colors.textSecondary} />
</TouchableOpacity> </TouchableOpacity>
) : null} ) : null}
<AntDesign <AntDesign
name={isOpen ? "up" : "down"} name={isOpen ? "up" : "down"}
size={14} size={14}
color="#999" color={colors.textSecondary}
style={styles.arrow} style={styles.arrow}
/> />
</View> </View>
</TouchableOpacity> </TouchableOpacity>
{isOpen && ( {isOpen && (
<View style={[styles.dropdown, { top: containerHeight }]}> <View
style={[
styles.dropdown,
{
top: containerHeight,
backgroundColor: colors.background,
borderColor: colors.border,
},
]}
>
{showSearch && ( {showSearch && (
<TextInput <TextInput
style={styles.searchInput} style={[
styles.searchInput,
{
backgroundColor: colors.background,
borderColor: colors.border,
color: colors.text,
},
]}
placeholder="Search..." placeholder="Search..."
placeholderTextColor={colors.textSecondary}
value={searchText} value={searchText}
onChangeText={setSearchText} onChangeText={setSearchText}
autoFocus autoFocus
@@ -160,8 +189,13 @@ const Select: React.FC<SelectProps> = ({
key={item.value} key={item.value}
style={[ style={[
styles.option, styles.option,
{
borderBottomColor: colors.separator,
},
item.disabled && styles.optionDisabled, item.disabled && styles.optionDisabled,
selectedValue === item.value && styles.optionSelected, selectedValue === item.value && {
backgroundColor: colors.primary + "20", // Add transparency to primary color
},
]} ]}
onPress={() => !item.disabled && handleSelect(item.value)} onPress={() => !item.disabled && handleSelect(item.value)}
disabled={item.disabled} disabled={item.disabled}
@@ -169,14 +203,22 @@ const Select: React.FC<SelectProps> = ({
<Text <Text
style={[ style={[
styles.optionText, styles.optionText,
item.disabled && styles.optionTextDisabled, {
selectedValue === item.value && styles.optionTextSelected, color: colors.text,
},
item.disabled && {
color: colors.textSecondary,
},
selectedValue === item.value && {
color: colors.primary,
fontWeight: "600",
},
]} ]}
> >
{item.label} {item.label}
</Text> </Text>
{selectedValue === item.value && ( {selectedValue === item.value && (
<AntDesign name="check" size={16} color="#4ecdc4" /> <AntDesign name="check" size={16} color={colors.primary} />
)} )}
</TouchableOpacity> </TouchableOpacity>
))} ))}
@@ -193,9 +235,7 @@ const styles = StyleSheet.create({
}, },
container: { container: {
borderWidth: 1, borderWidth: 1,
borderColor: "#e6e6e6",
borderRadius: 8, borderRadius: 8,
backgroundColor: "#fff",
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
justifyContent: "space-between", justifyContent: "space-between",
@@ -204,7 +244,7 @@ const styles = StyleSheet.create({
flex: 1, flex: 1,
}, },
text: { text: {
color: "#111", // Color is set dynamically via theme
}, },
suffix: { suffix: {
flexDirection: "row", flexDirection: "row",
@@ -220,9 +260,7 @@ const styles = StyleSheet.create({
position: "absolute", position: "absolute",
left: 0, left: 0,
right: 0, right: 0,
backgroundColor: "#fff",
borderWidth: 1, borderWidth: 1,
borderColor: "#e6e6e6",
borderTopWidth: 0, borderTopWidth: 0,
borderRadius: 10, borderRadius: 10,
borderBottomLeftRadius: 8, borderBottomLeftRadius: 8,
@@ -236,7 +274,6 @@ const styles = StyleSheet.create({
}, },
searchInput: { searchInput: {
borderWidth: 1, borderWidth: 1,
borderColor: "#e6e6e6",
borderRadius: 4, borderRadius: 4,
padding: 8, padding: 8,
margin: 8, margin: 8,
@@ -247,7 +284,6 @@ const styles = StyleSheet.create({
option: { option: {
padding: 12, padding: 12,
borderBottomWidth: 1, borderBottomWidth: 1,
borderBottomColor: "#f0f0f0",
flexDirection: "row", flexDirection: "row",
justifyContent: "space-between", justifyContent: "space-between",
alignItems: "center", alignItems: "center",
@@ -255,20 +291,11 @@ const styles = StyleSheet.create({
optionDisabled: { optionDisabled: {
opacity: 0.5, opacity: 0.5,
}, },
optionSelected: { // optionSelected is handled dynamically via inline styles
backgroundColor: "#f6ffed",
},
optionText: { optionText: {
fontSize: 16, fontSize: 16,
color: "#111",
},
optionTextDisabled: {
color: "#999",
},
optionTextSelected: {
color: "#4ecdc4",
fontWeight: "600",
}, },
// optionTextDisabled and optionTextSelected are handled dynamically via inline styles
}); });
export default Select; export default Select;

View File

@@ -1,4 +1,6 @@
import { Text, View } from "react-native"; import { ThemedText } from "@/components/themed-text";
import { useAppTheme } from "@/hooks/use-app-theme";
import { View } from "react-native";
interface DescriptionProps { interface DescriptionProps {
title?: string; title?: string;
@@ -8,10 +10,15 @@ export const Description = ({
title = "", title = "",
description = "", description = "",
}: DescriptionProps) => { }: DescriptionProps) => {
const { colors } = useAppTheme();
return ( return (
<View className="flex-row gap-2 "> <View className="flex-row gap-2 ">
<Text className="opacity-50 text-lg">{title}:</Text> <ThemedText
<Text className="text-lg">{description}</Text> style={{ color: colors.textSecondary, fontSize: 16 }}
>
{title}:
</ThemedText>
<ThemedText style={{ fontSize: 16 }}>{description}</ThemedText>
</View> </View>
); );
}; };

View File

@@ -1,3 +1,4 @@
import { useAppTheme } from "@/hooks/use-app-theme";
import { useI18n } from "@/hooks/use-i18n"; import { useI18n } from "@/hooks/use-i18n";
import { convertToDMS, kmhToKnot } from "@/utils/geom"; import { convertToDMS, kmhToKnot } from "@/utils/geom";
import { MaterialIcons } from "@expo/vector-icons"; import { MaterialIcons } from "@expo/vector-icons";
@@ -15,6 +16,8 @@ const GPSInfoPanel = ({ gpsData }: GPSInfoPanelProps) => {
const translateY = useRef(new Animated.Value(0)).current; const translateY = useRef(new Animated.Value(0)).current;
const blockBottom = useRef(new Animated.Value(0)).current; const blockBottom = useRef(new Animated.Value(0)).current;
const { t } = useI18n(); const { t } = useI18n();
const { colors, styles } = useAppTheme();
useEffect(() => { useEffect(() => {
Animated.timing(translateY, { Animated.timing(translateY, {
toValue: isExpanded ? 0 : 200, // Dịch chuyển xuống 200px khi thu gọn toValue: isExpanded ? 0 : 200, // Dịch chuyển xuống 200px khi thu gọn
@@ -44,45 +47,35 @@ const GPSInfoPanel = ({ gpsData }: GPSInfoPanelProps) => {
position: "absolute", position: "absolute",
bottom: blockBottom, bottom: blockBottom,
left: 5, left: 5,
// width: 48,
// height: 48,
// backgroundColor: "blue",
borderRadius: 4, borderRadius: 4,
zIndex: 30, zIndex: 30,
}} }}
> >
<ButtonCreateNewHaulOrTrip gpsData={gpsData} /> <ButtonCreateNewHaulOrTrip gpsData={gpsData} />
{/* <TouchableOpacity
onPress={() => {
// showInfoToast("oad");
showWarningToast("This is a warning toast!");
}}
className="absolute top-2 right-2 z-10 bg-white rounded-full p-1"
>
<MaterialIcons
name={isExpanded ? "close" : "close"}
size={20}
color="#666"
/>
</TouchableOpacity> */}
</Animated.View> </Animated.View>
<Animated.View <Animated.View
style={{ style={[
transform: [{ translateY }], styles.card,
}} {
className="absolute bottom-0 gap-3 right-0 p-3 left-0 h-auto w-full rounded-t-xl bg-white shadow-md" transform: [{ translateY }],
backgroundColor: colors.card,
borderRadius: 0,
},
]}
className="absolute bottom-0 gap-5 right-0 px-4 pt-12 pb-2 left-0 h-auto w-full rounded-t-xl shadow-md"
onLayout={(event) => setPanelHeight(event.nativeEvent.layout.height)} onLayout={(event) => setPanelHeight(event.nativeEvent.layout.height)}
> >
{/* Nút toggle ở top-right */} {/* Nút toggle ở top-right */}
<TouchableOpacity <TouchableOpacity
onPress={togglePanel} onPress={togglePanel}
className="absolute top-2 right-2 z-10 bg-white rounded-full p-1" className="absolute top-2 right-2 z-10 rounded-full p-1"
style={{ backgroundColor: colors.card }}
> >
<MaterialIcons <MaterialIcons
name={isExpanded ? "close" : "close"} name={isExpanded ? "close" : "close"}
size={20} size={20}
color="#666" color={colors.icon}
/> />
</TouchableOpacity> </TouchableOpacity>
@@ -120,9 +113,10 @@ const GPSInfoPanel = ({ gpsData }: GPSInfoPanelProps) => {
{!isExpanded && ( {!isExpanded && (
<TouchableOpacity <TouchableOpacity
onPress={togglePanel} onPress={togglePanel}
className="absolute bottom-5 right-2 z-20 bg-white rounded-full p-2 shadow-lg" className="absolute bottom-5 right-2 z-20 rounded-full p-2 shadow-lg"
style={{ backgroundColor: colors.card }}
> >
<MaterialIcons name="info-outline" size={24} /> <MaterialIcons name="info-outline" size={24} color={colors.icon} />
</TouchableOpacity> </TouchableOpacity>
)} )}
</> </>

View File

@@ -12,6 +12,7 @@ import { StyleSheet, Text, TextInput, View } from "react-native";
import IconButton from "../IconButton"; import IconButton from "../IconButton";
import Select from "../Select"; import Select from "../Select";
import Modal from "../ui/modal"; import Modal from "../ui/modal";
import { useThemeColor } from "@/hooks/use-theme-color";
const SosButton = () => { const SosButton = () => {
const [sosData, setSosData] = useState<Model.SosResponse | null>(); const [sosData, setSosData] = useState<Model.SosResponse | null>();
@@ -22,6 +23,16 @@ const SosButton = () => {
const [customMessage, setCustomMessage] = useState(""); const [customMessage, setCustomMessage] = useState("");
const [errors, setErrors] = useState<{ [key: string]: string }>({}); const [errors, setErrors] = useState<{ [key: string]: string }>({});
const { t } = useI18n(); const { t } = useI18n();
// Theme colors
const textColor = useThemeColor({}, 'text');
const borderColor = useThemeColor({}, 'border');
const errorColor = useThemeColor({}, 'error');
const backgroundColor = useThemeColor({}, 'background');
// Dynamic styles
const styles = SosButtonStyles(textColor, borderColor, errorColor, backgroundColor);
const sosOptions = [ const sosOptions = [
...sosMessage.map((msg) => ({ ...sosMessage.map((msg) => ({
ma: msg.ma, ma: msg.ma,
@@ -176,7 +187,7 @@ const SosButton = () => {
errors.customMessage ? styles.errorInput : {}, errors.customMessage ? styles.errorInput : {},
]} ]}
placeholder={t("home.sos.enterStatus")} placeholder={t("home.sos.enterStatus")}
placeholderTextColor="#999" placeholderTextColor={textColor + '99'} // Add transparency
value={customMessage} value={customMessage}
onChangeText={(text) => { onChangeText={(text) => {
setCustomMessage(text); setCustomMessage(text);
@@ -201,7 +212,7 @@ const SosButton = () => {
); );
}; };
const styles = StyleSheet.create({ const SosButtonStyles = (textColor: string, borderColor: string, errorColor: string, backgroundColor: string) => StyleSheet.create({
formGroup: { formGroup: {
marginBottom: 16, marginBottom: 16,
}, },
@@ -209,26 +220,27 @@ const styles = StyleSheet.create({
fontSize: 14, fontSize: 14,
fontWeight: "600", fontWeight: "600",
marginBottom: 8, marginBottom: 8,
color: "#333", color: textColor,
}, },
errorBorder: { errorBorder: {
borderColor: "#ff4444", borderColor: errorColor,
}, },
input: { input: {
borderWidth: 1, borderWidth: 1,
borderColor: "#ddd", borderColor: borderColor,
borderRadius: 8, borderRadius: 8,
paddingHorizontal: 12, paddingHorizontal: 12,
paddingVertical: 12, paddingVertical: 12,
fontSize: 14, fontSize: 14,
color: "#333", color: textColor,
backgroundColor: backgroundColor,
textAlignVertical: "top", textAlignVertical: "top",
}, },
errorInput: { errorInput: {
borderColor: "#ff4444", borderColor: errorColor,
}, },
errorText: { errorText: {
color: "#ff4444", color: errorColor,
fontSize: 12, fontSize: 12,
marginTop: 4, marginTop: 4,
}, },

View File

@@ -80,7 +80,7 @@ const createStyles = (colors: any) =>
borderRadius: 8, borderRadius: 8,
padding: 12, padding: 12,
marginBottom: 12, marginBottom: 12,
backgroundColor: colors.backgroundSecondary, backgroundColor: colors.surfaceSecondary,
}, },
infoRow: { infoRow: {
flexDirection: "row", flexDirection: "row",

View File

@@ -58,7 +58,7 @@ export const createStyles = (colors: typeof Colors.light) =>
marginBottom: 15, marginBottom: 15,
}, },
fishCard: { fishCard: {
backgroundColor: colors.card, backgroundColor: colors.surfaceSecondary,
borderRadius: 12, borderRadius: 12,
padding: 16, padding: 16,
marginBottom: 16, marginBottom: 16,
@@ -95,7 +95,7 @@ export const createStyles = (colors: typeof Colors.light) =>
}, },
input: { input: {
borderWidth: 1, borderWidth: 1,
borderColor: colors.border, borderColor: colors.primary,
borderRadius: 8, borderRadius: 8,
paddingHorizontal: 12, paddingHorizontal: 12,
paddingVertical: 10, paddingVertical: 10,
@@ -106,7 +106,7 @@ export const createStyles = (colors: typeof Colors.light) =>
inputDisabled: { inputDisabled: {
backgroundColor: colors.backgroundSecondary, backgroundColor: colors.backgroundSecondary,
color: colors.textSecondary, color: colors.textSecondary,
borderColor: colors.separator, borderColor: colors.border,
}, },
errorText: { errorText: {
color: colors.error, color: colors.error,

View File

@@ -1,6 +1,6 @@
import { Ionicons } from "@expo/vector-icons"; import { Ionicons } from "@expo/vector-icons";
import type { ComponentProps } from "react"; import type { ComponentProps } from "react";
import { useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { import {
Animated, Animated,
OpaqueColorValue, OpaqueColorValue,
@@ -29,7 +29,7 @@ const PRESS_FEEDBACK_DURATION = 120;
type IoniconName = ComponentProps<typeof Ionicons>["name"]; type IoniconName = ComponentProps<typeof Ionicons>["name"];
type RotateSwitchProps = { type SliceSwitchProps = {
size?: SwitchSize; size?: SwitchSize;
leftIcon?: IoniconName; leftIcon?: IoniconName;
leftIconColor?: string | OpaqueColorValue | undefined; leftIconColor?: string | OpaqueColorValue | undefined;
@@ -42,6 +42,7 @@ type RotateSwitchProps = {
activeOverlayColor?: string; activeOverlayColor?: string;
style?: StyleProp<ViewStyle>; style?: StyleProp<ViewStyle>;
onChange?: (value: boolean) => void; onChange?: (value: boolean) => void;
value?: boolean;
}; };
const SliceSwitch = ({ const SliceSwitch = ({
@@ -57,19 +58,28 @@ const SliceSwitch = ({
activeOverlayColor = "#000", activeOverlayColor = "#000",
style, style,
onChange, onChange,
}: RotateSwitchProps) => { value,
}: SliceSwitchProps) => {
const { width: containerWidth, height: containerHeight } = const { width: containerWidth, height: containerHeight } =
SIZE_PRESETS[size] ?? SIZE_PRESETS.md; SIZE_PRESETS[size] ?? SIZE_PRESETS.md;
const animationDuration = Math.max(duration ?? DEFAULT_TOGGLE_DURATION, 0); const animationDuration = Math.max(duration ?? DEFAULT_TOGGLE_DURATION, 0);
const [isOn, setIsOn] = useState(false); const [isOn, setIsOn] = useState(value ?? false);
const [bgOn, setBgOn] = useState(false); const [bgOn, setBgOn] = useState(value ?? false);
const progress = useRef(new Animated.Value(0)).current; const progress = useRef(new Animated.Value(value ? 1 : 0)).current;
const pressScale = useRef(new Animated.Value(1)).current; const pressScale = useRef(new Animated.Value(1)).current;
const overlayTranslateX = useRef(new Animated.Value(0)).current; const overlayTranslateX = useRef(
new Animated.Value(value ? containerWidth / 2 : 0)
).current;
const listenerIdRef = useRef<string | number | null>(null); const listenerIdRef = useRef<string | number | null>(null);
const handleToggle = () => { // Sync with external value prop if provided
const next = !isOn; useEffect(() => {
if (value !== undefined && value !== isOn) {
animateToValue(value);
}
}, [value]);
const animateToValue = (next: boolean) => {
const targetValue = next ? 1 : 0; const targetValue = next ? 1 : 0;
const overlayTarget = next ? containerWidth / 2 : 0; const overlayTarget = next ? containerWidth / 2 : 0;
@@ -81,7 +91,6 @@ const SliceSwitch = ({
overlayTranslateX.setValue(overlayTarget); overlayTranslateX.setValue(overlayTarget);
setIsOn(next); setIsOn(next);
setBgOn(next); setBgOn(next);
onChange?.(next);
return; return;
} }
@@ -100,7 +109,6 @@ const SliceSwitch = ({
}), }),
]).start(() => { ]).start(() => {
setBgOn(next); setBgOn(next);
onChange?.(next);
}); });
// Remove any previous listener // Remove any previous listener
@@ -132,6 +140,14 @@ const SliceSwitch = ({
}); });
}; };
const handleToggle = () => {
const next = !isOn;
if (value === undefined) {
animateToValue(next);
}
onChange?.(next);
};
const handlePressIn = () => { const handlePressIn = () => {
pressScale.stopAnimation(); pressScale.stopAnimation();
Animated.timing(pressScale, { Animated.timing(pressScale, {

View File

@@ -3,9 +3,9 @@
* Provides styled components and theme utilities * Provides styled components and theme utilities
*/ */
import { useThemeContext } from "@/hooks/use-theme-context";
import { useMemo } from "react"; import { useMemo } from "react";
import { StyleSheet, TextStyle, ViewStyle } from "react-native"; import { StyleSheet, TextStyle, ViewStyle } from "react-native";
import { useThemeContext } from "@/hooks/use-theme-context";
export function useAppTheme() { export function useAppTheme() {
const { colors, colorScheme, themeMode, setThemeMode, getColor } = const { colors, colorScheme, themeMode, setThemeMode, getColor } =

View File

@@ -58,6 +58,7 @@
} }
}, },
"trip": { "trip": {
"infoTrip": "Trip Information",
"createNewTrip": "Create New Trip", "createNewTrip": "Create New Trip",
"endTrip": "End Trip", "endTrip": "End Trip",
"cancelTrip": "Cancel Trip", "cancelTrip": "Cancel Trip",

View File

@@ -58,6 +58,7 @@
} }
}, },
"trip": { "trip": {
"infoTrip": "Thông Tin Chuyến Đi",
"createNewTrip": "Tạo chuyến mới", "createNewTrip": "Tạo chuyến mới",
"endTrip": "Kết thúc chuyến", "endTrip": "Kết thúc chuyến",
"cancelTrip": "Hủy chuyến", "cancelTrip": "Hủy chuyến",