them icon
This commit is contained in:
@@ -20,21 +20,30 @@ export default function TabLayout() {
|
|||||||
<Tabs.Screen
|
<Tabs.Screen
|
||||||
name="index"
|
name="index"
|
||||||
options={{
|
options={{
|
||||||
title: "Home",
|
title: "Giám sát",
|
||||||
tabBarIcon: ({ color }) => (
|
tabBarIcon: ({ color }) => (
|
||||||
<IconSymbol size={28} name="house.fill" color={color} />
|
<IconSymbol size={28} name="map.fill" color={color} />
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Tabs.Screen
|
<Tabs.Screen
|
||||||
name="explore"
|
name="explore"
|
||||||
options={{
|
options={{
|
||||||
title: "Thông Tin Chuyến Đi",
|
title: "Explore",
|
||||||
tabBarIcon: ({ color }) => (
|
tabBarIcon: ({ color }) => (
|
||||||
<IconSymbol size={28} name="paperplane.fill" color={color} />
|
<IconSymbol size={28} name="paperplane.fill" color={color} />
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Tabs.Screen
|
||||||
|
name="tripInfo"
|
||||||
|
options={{
|
||||||
|
title: "Thông Tin Chuyến Đi",
|
||||||
|
tabBarIcon: ({ color }) => (
|
||||||
|
<IconSymbol size={28} name="ferry.fill" color={color} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<Tabs.Screen
|
<Tabs.Screen
|
||||||
name="setting"
|
name="setting"
|
||||||
options={{
|
options={{
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import { Image } from 'expo-image';
|
import { Image } from "expo-image";
|
||||||
import { Platform, StyleSheet } from 'react-native';
|
import { Platform, StyleSheet } from "react-native";
|
||||||
|
|
||||||
import { Collapsible } from '@/components/ui/collapsible';
|
import { ExternalLink } from "@/components/external-link";
|
||||||
import { ExternalLink } from '@/components/external-link';
|
import ParallaxScrollView from "@/components/parallax-scroll-view";
|
||||||
import ParallaxScrollView from '@/components/parallax-scroll-view';
|
import { ThemedText } from "@/components/themed-text";
|
||||||
import { ThemedText } from '@/components/themed-text';
|
import { ThemedView } from "@/components/themed-view";
|
||||||
import { ThemedView } from '@/components/themed-view';
|
import { Collapsible } from "@/components/ui/collapsible";
|
||||||
import { IconSymbol } from '@/components/ui/icon-symbol';
|
import { IconSymbol } from "@/components/ui/icon-symbol";
|
||||||
import { Fonts } from '@/constants/theme';
|
import { Fonts } from "@/constants/theme";
|
||||||
|
|
||||||
export default function TabTwoScreen() {
|
export default function TabTwoScreen() {
|
||||||
return (
|
return (
|
||||||
<ParallaxScrollView
|
<ParallaxScrollView
|
||||||
headerBackgroundColor={{ light: '#D0D0D0', dark: '#353636' }}
|
headerBackgroundColor={{ light: "#D0D0D0", dark: "#353636" }}
|
||||||
headerImage={
|
headerImage={
|
||||||
<IconSymbol
|
<IconSymbol
|
||||||
size={310}
|
size={310}
|
||||||
@@ -20,25 +20,31 @@ export default function TabTwoScreen() {
|
|||||||
name="chevron.left.forwardslash.chevron.right"
|
name="chevron.left.forwardslash.chevron.right"
|
||||||
style={styles.headerImage}
|
style={styles.headerImage}
|
||||||
/>
|
/>
|
||||||
}>
|
}
|
||||||
|
>
|
||||||
<ThemedView style={styles.titleContainer}>
|
<ThemedView style={styles.titleContainer}>
|
||||||
<ThemedText
|
<ThemedText
|
||||||
type="title"
|
type="title"
|
||||||
style={{
|
style={{
|
||||||
fontFamily: Fonts.rounded,
|
fontFamily: Fonts.rounded,
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
Explore
|
Explore
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
</ThemedView>
|
</ThemedView>
|
||||||
<ThemedText>This app includes example code to help you get started.</ThemedText>
|
<ThemedText>
|
||||||
|
This app includes example code to help you get started.
|
||||||
|
</ThemedText>
|
||||||
<Collapsible title="File-based routing">
|
<Collapsible title="File-based routing">
|
||||||
<ThemedText>
|
<ThemedText>
|
||||||
This app has two screens:{' '}
|
This app has two screens:{" "}
|
||||||
<ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> and{' '}
|
<ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText>{" "}
|
||||||
|
and{" "}
|
||||||
<ThemedText type="defaultSemiBold">app/(tabs)/explore.tsx</ThemedText>
|
<ThemedText type="defaultSemiBold">app/(tabs)/explore.tsx</ThemedText>
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
<ThemedText>
|
<ThemedText>
|
||||||
The layout file in <ThemedText type="defaultSemiBold">app/(tabs)/_layout.tsx</ThemedText>{' '}
|
The layout file in{" "}
|
||||||
|
<ThemedText type="defaultSemiBold">app/(tabs)/_layout.tsx</ThemedText>{" "}
|
||||||
sets up the tab navigator.
|
sets up the tab navigator.
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
<ExternalLink href="https://docs.expo.dev/router/introduction">
|
<ExternalLink href="https://docs.expo.dev/router/introduction">
|
||||||
@@ -47,19 +53,21 @@ export default function TabTwoScreen() {
|
|||||||
</Collapsible>
|
</Collapsible>
|
||||||
<Collapsible title="Android, iOS, and web support">
|
<Collapsible title="Android, iOS, and web support">
|
||||||
<ThemedText>
|
<ThemedText>
|
||||||
You can open this project on Android, iOS, and the web. To open the web version, press{' '}
|
You can open this project on Android, iOS, and the web. To open the
|
||||||
<ThemedText type="defaultSemiBold">w</ThemedText> in the terminal running this project.
|
web version, press <ThemedText type="defaultSemiBold">w</ThemedText>{" "}
|
||||||
|
in the terminal running this project.
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
<Collapsible title="Images">
|
<Collapsible title="Images">
|
||||||
<ThemedText>
|
<ThemedText>
|
||||||
For static images, you can use the <ThemedText type="defaultSemiBold">@2x</ThemedText> and{' '}
|
For static images, you can use the{" "}
|
||||||
<ThemedText type="defaultSemiBold">@3x</ThemedText> suffixes to provide files for
|
<ThemedText type="defaultSemiBold">@2x</ThemedText> and{" "}
|
||||||
different screen densities
|
<ThemedText type="defaultSemiBold">@3x</ThemedText> suffixes to
|
||||||
|
provide files for different screen densities
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
<Image
|
<Image
|
||||||
source={require('@/assets/images/react-logo.png')}
|
source={require("@/assets/images/react-logo.png")}
|
||||||
style={{ width: 100, height: 100, alignSelf: 'center' }}
|
style={{ width: 100, height: 100, alignSelf: "center" }}
|
||||||
/>
|
/>
|
||||||
<ExternalLink href="https://reactnative.dev/docs/images">
|
<ExternalLink href="https://reactnative.dev/docs/images">
|
||||||
<ThemedText type="link">Learn more</ThemedText>
|
<ThemedText type="link">Learn more</ThemedText>
|
||||||
@@ -67,9 +75,10 @@ export default function TabTwoScreen() {
|
|||||||
</Collapsible>
|
</Collapsible>
|
||||||
<Collapsible title="Light and dark mode components">
|
<Collapsible title="Light and dark mode components">
|
||||||
<ThemedText>
|
<ThemedText>
|
||||||
This template has light and dark mode support. The{' '}
|
This template has light and dark mode support. The{" "}
|
||||||
<ThemedText type="defaultSemiBold">useColorScheme()</ThemedText> hook lets you inspect
|
<ThemedText type="defaultSemiBold">useColorScheme()</ThemedText> hook
|
||||||
what the user's current color scheme is, and so you can adjust UI colors accordingly.
|
lets you inspect what the user's current color scheme is, and so
|
||||||
|
you can adjust UI colors accordingly.
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
<ExternalLink href="https://docs.expo.dev/develop/user-interface/color-themes/">
|
<ExternalLink href="https://docs.expo.dev/develop/user-interface/color-themes/">
|
||||||
<ThemedText type="link">Learn more</ThemedText>
|
<ThemedText type="link">Learn more</ThemedText>
|
||||||
@@ -77,18 +86,23 @@ export default function TabTwoScreen() {
|
|||||||
</Collapsible>
|
</Collapsible>
|
||||||
<Collapsible title="Animations">
|
<Collapsible title="Animations">
|
||||||
<ThemedText>
|
<ThemedText>
|
||||||
This template includes an example of an animated component. The{' '}
|
This template includes an example of an animated component. The{" "}
|
||||||
<ThemedText type="defaultSemiBold">components/HelloWave.tsx</ThemedText> component uses
|
<ThemedText type="defaultSemiBold">
|
||||||
the powerful{' '}
|
components/HelloWave.tsx
|
||||||
|
</ThemedText>{" "}
|
||||||
|
component uses the powerful{" "}
|
||||||
<ThemedText type="defaultSemiBold" style={{ fontFamily: Fonts.mono }}>
|
<ThemedText type="defaultSemiBold" style={{ fontFamily: Fonts.mono }}>
|
||||||
react-native-reanimated
|
react-native-reanimated
|
||||||
</ThemedText>{' '}
|
</ThemedText>{" "}
|
||||||
library to create a waving hand animation.
|
library to create a waving hand animation.
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
{Platform.select({
|
{Platform.select({
|
||||||
ios: (
|
ios: (
|
||||||
<ThemedText>
|
<ThemedText>
|
||||||
The <ThemedText type="defaultSemiBold">components/ParallaxScrollView.tsx</ThemedText>{' '}
|
The{" "}
|
||||||
|
<ThemedText type="defaultSemiBold">
|
||||||
|
components/ParallaxScrollView.tsx
|
||||||
|
</ThemedText>{" "}
|
||||||
component provides a parallax effect for the header image.
|
component provides a parallax effect for the header image.
|
||||||
</ThemedText>
|
</ThemedText>
|
||||||
),
|
),
|
||||||
@@ -100,13 +114,13 @@ export default function TabTwoScreen() {
|
|||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
headerImage: {
|
headerImage: {
|
||||||
color: '#808080',
|
color: "#808080",
|
||||||
bottom: -90,
|
bottom: -90,
|
||||||
left: -35,
|
left: -35,
|
||||||
position: 'absolute',
|
position: "absolute",
|
||||||
},
|
},
|
||||||
titleContainer: {
|
titleContainer: {
|
||||||
flexDirection: 'row',
|
flexDirection: "row",
|
||||||
gap: 8,
|
gap: 8,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
22
app/(tabs)/tripInfo.tsx
Normal file
22
app/(tabs)/tripInfo.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { ThemedText } from "@/components/themed-text";
|
||||||
|
import { ThemedView } from "@/components/themed-view";
|
||||||
|
import TripCostTable from "@/components/tripInfo/TripCostTable";
|
||||||
|
import { StyleSheet } from "react-native";
|
||||||
|
|
||||||
|
export default function TripInfoScreen() {
|
||||||
|
return (
|
||||||
|
<ThemedView style={styles.container}>
|
||||||
|
<ThemedText type="title">Thông Tin Chuyến Đi</ThemedText>
|
||||||
|
<TripCostTable />
|
||||||
|
</ThemedView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
padding: 20,
|
||||||
|
},
|
||||||
|
});
|
||||||
60
components/tripInfo/TripCostTable.styles.ts
Normal file
60
components/tripInfo/TripCostTable.styles.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import { StyleSheet } from "react-native";
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
width: "100%",
|
||||||
|
margin: 16,
|
||||||
|
padding: 16,
|
||||||
|
borderRadius: 12,
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
shadowColor: "#000",
|
||||||
|
shadowOpacity: 0.1,
|
||||||
|
shadowRadius: 4,
|
||||||
|
elevation: 2,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: "700",
|
||||||
|
textAlign: "center",
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
row: {
|
||||||
|
flexDirection: "row",
|
||||||
|
borderBottomWidth: 0.5,
|
||||||
|
borderColor: "#ddd",
|
||||||
|
paddingVertical: 8,
|
||||||
|
},
|
||||||
|
cell: {
|
||||||
|
flex: 1,
|
||||||
|
textAlign: "center",
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
left: {
|
||||||
|
textAlign: "left",
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
backgroundColor: "#f8f8f8",
|
||||||
|
borderTopWidth: 1,
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
},
|
||||||
|
headerText: {
|
||||||
|
fontWeight: "600",
|
||||||
|
},
|
||||||
|
highlight: {
|
||||||
|
color: "#ff6600",
|
||||||
|
fontWeight: "600",
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
marginTop: 6,
|
||||||
|
},
|
||||||
|
footerText: {
|
||||||
|
fontWeight: "600",
|
||||||
|
color: "#007bff",
|
||||||
|
},
|
||||||
|
total: {
|
||||||
|
color: "#007bff",
|
||||||
|
fontWeight: "700",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default styles;
|
||||||
100
components/tripInfo/TripCostTable.tsx
Normal file
100
components/tripInfo/TripCostTable.tsx
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { FlatList, ListRenderItem, Text, View } from "react-native";
|
||||||
|
import styles from "./TripCostTable.styles";
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// 🧩 Interface
|
||||||
|
// ---------------------------
|
||||||
|
interface CostItem {
|
||||||
|
id: string;
|
||||||
|
loai: string;
|
||||||
|
soLuong: number;
|
||||||
|
donVi: string;
|
||||||
|
chiPhi: number;
|
||||||
|
tongChiPhi: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// 📊 Dữ liệu mẫu
|
||||||
|
// ---------------------------
|
||||||
|
const data: CostItem[] = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
loai: "Nhiên liệu",
|
||||||
|
soLuong: 1000,
|
||||||
|
donVi: "liters",
|
||||||
|
chiPhi: 20000,
|
||||||
|
tongChiPhi: 20000000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
loai: "Lương thực",
|
||||||
|
soLuong: 500,
|
||||||
|
donVi: "kg",
|
||||||
|
chiPhi: 30000,
|
||||||
|
tongChiPhi: 15000000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
loai: "Lương thuyền viên",
|
||||||
|
soLuong: 10,
|
||||||
|
donVi: "people",
|
||||||
|
chiPhi: 5000000,
|
||||||
|
tongChiPhi: 50000000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "4",
|
||||||
|
loai: "Muối đá",
|
||||||
|
soLuong: 100,
|
||||||
|
donVi: "kg",
|
||||||
|
chiPhi: 20000,
|
||||||
|
tongChiPhi: 2000000,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// 💰 Component chính
|
||||||
|
// ---------------------------
|
||||||
|
const TripCostTable: React.FC = () => {
|
||||||
|
const tongCong = data.reduce((sum, item) => sum + item.tongChiPhi, 0);
|
||||||
|
|
||||||
|
const renderItem: ListRenderItem<CostItem> = ({ item }) => (
|
||||||
|
<View style={styles.row}>
|
||||||
|
<Text style={[styles.cell, styles.left]}>{item.loai}</Text>
|
||||||
|
<Text style={[styles.cell, styles.highlight]}>
|
||||||
|
{item.tongChiPhi.toLocaleString()}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Text style={styles.title}>Chi phí chuyến đi</Text>
|
||||||
|
|
||||||
|
{/* Header */}
|
||||||
|
<View style={[styles.row, styles.header]}>
|
||||||
|
<Text style={[styles.cell, styles.left, styles.headerText]}>Loại</Text>
|
||||||
|
<Text style={[styles.cell, styles.headerText]}>Tổng chi phí</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* Body */}
|
||||||
|
<FlatList
|
||||||
|
data={data}
|
||||||
|
renderItem={renderItem}
|
||||||
|
keyExtractor={(item) => item.id}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Footer */}
|
||||||
|
<View style={[styles.row, styles.footer]}>
|
||||||
|
<Text style={[styles.cell, styles.left, styles.footerText]}>
|
||||||
|
Tổng cộng
|
||||||
|
</Text>
|
||||||
|
<Text style={[styles.cell, styles.total]}>
|
||||||
|
{tongCong.toLocaleString()}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TripCostTable;
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
// Fallback for using MaterialIcons on Android and web.
|
// Fallback for using MaterialIcons on Android and web.
|
||||||
|
|
||||||
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
|
import MaterialIcons from "@expo/vector-icons/MaterialIcons";
|
||||||
import { SymbolWeight, SymbolViewProps } from 'expo-symbols';
|
import { SymbolViewProps, SymbolWeight } from "expo-symbols";
|
||||||
import { ComponentProps } from 'react';
|
import { ComponentProps } from "react";
|
||||||
import { OpaqueColorValue, type StyleProp, type TextStyle } from 'react-native';
|
import { OpaqueColorValue, type StyleProp, type TextStyle } from "react-native";
|
||||||
|
|
||||||
type IconMapping = Record<SymbolViewProps['name'], ComponentProps<typeof MaterialIcons>['name']>;
|
type IconMapping = Record<
|
||||||
|
SymbolViewProps["name"],
|
||||||
|
ComponentProps<typeof MaterialIcons>["name"]
|
||||||
|
>;
|
||||||
type IconSymbolName = keyof typeof MAPPING;
|
type IconSymbolName = keyof typeof MAPPING;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -14,10 +17,12 @@ type IconSymbolName = keyof typeof MAPPING;
|
|||||||
* - see SF Symbols in the [SF Symbols](https://developer.apple.com/sf-symbols/) app.
|
* - see SF Symbols in the [SF Symbols](https://developer.apple.com/sf-symbols/) app.
|
||||||
*/
|
*/
|
||||||
const MAPPING = {
|
const MAPPING = {
|
||||||
'house.fill': 'home',
|
"house.fill": "home",
|
||||||
'paperplane.fill': 'send',
|
"paperplane.fill": "send",
|
||||||
'chevron.left.forwardslash.chevron.right': 'code',
|
"chevron.left.forwardslash.chevron.right": "code",
|
||||||
'chevron.right': 'chevron-right',
|
"chevron.right": "chevron-right",
|
||||||
|
"ferry.fill": "directions-boat",
|
||||||
|
"map.fill": "map",
|
||||||
} as IconMapping;
|
} as IconMapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,5 +42,12 @@ export function IconSymbol({
|
|||||||
style?: StyleProp<TextStyle>;
|
style?: StyleProp<TextStyle>;
|
||||||
weight?: SymbolWeight;
|
weight?: SymbolWeight;
|
||||||
}) {
|
}) {
|
||||||
return <MaterialIcons color={color} size={size} name={MAPPING[name]} style={style} />;
|
return (
|
||||||
|
<MaterialIcons
|
||||||
|
color={color}
|
||||||
|
size={size}
|
||||||
|
name={MAPPING[name]}
|
||||||
|
style={style}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ if [ -z "$current_branch" ]; then
|
|||||||
fi
|
fi
|
||||||
echo "👉 Bạn đang ở nhánh: $current_branch"
|
echo "👉 Bạn đang ở nhánh: $current_branch"
|
||||||
|
|
||||||
# Hỏi nhánh chính, mặc định là 'main' nếu người dùng không nhập
|
# Hỏi nhánh chính, mặc định là 'master' nếu người dùng không nhập
|
||||||
read -p "Nhập tên nhánh chính (mặc định: main): " target_branch
|
read -p "Nhập tên nhánh chính (mặc định: master): " target_branch
|
||||||
target_branch=${target_branch:-main}
|
target_branch=${target_branch:-master}
|
||||||
|
|
||||||
# Kiểm tra xem nhánh chính có tồn tại trên remote không
|
# Kiểm tra xem nhánh chính có tồn tại trên remote không
|
||||||
if ! git ls-remote --heads origin "$target_branch" >/dev/null 2>&1; then
|
if ! git ls-remote --heads origin "$target_branch" >/dev/null 2>&1; then
|
||||||
|
|||||||
Reference in New Issue
Block a user