update login, modal detail in tripInfo

This commit is contained in:
2025-11-01 19:47:45 +07:00
parent eea1482a88
commit 52d2f0f78b
11 changed files with 674 additions and 22 deletions

View File

@@ -1,4 +1,12 @@
import { Platform, ScrollView, StyleSheet, Text, View } from "react-native"; import { Link } from "expo-router";
import {
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
} from "react-native";
import { SafeAreaView } from "react-native-safe-area-context"; import { SafeAreaView } from "react-native-safe-area-context";
export default function Warning() { export default function Warning() {
@@ -7,6 +15,12 @@ export default function Warning() {
<ScrollView contentContainerStyle={styles.scrollContent}> <ScrollView contentContainerStyle={styles.scrollContent}>
<View style={styles.container}> <View style={styles.container}>
<Text style={styles.titleText}>Nhật Chuyến Đi</Text> <Text style={styles.titleText}>Nhật Chuyến Đi</Text>
<Link href="/modal" asChild>
<TouchableOpacity style={styles.button}>
<Text style={styles.buttonText}>Mở Modal</Text>
</TouchableOpacity>
</Link>
</View> </View>
</ScrollView> </ScrollView>
</SafeAreaView> </SafeAreaView>
@@ -32,4 +46,16 @@ const styles = StyleSheet.create({
default: "System", default: "System",
}), }),
}, },
button: {
backgroundColor: "#007AFF",
paddingVertical: 14,
paddingHorizontal: 24,
borderRadius: 8,
marginTop: 20,
},
buttonText: {
color: "#fff",
fontSize: 16,
fontWeight: "600",
},
}); });

View File

@@ -108,14 +108,6 @@ export default function LoginScreen() {
<ThemedText type="title" style={styles.title}> <ThemedText type="title" style={styles.title}>
Hệ thống giám sát tàu Hệ thống giám sát tàu
</ThemedText> </ThemedText>
{/* Owner Logo */}
<View style={styles.ownerContainer}>
<Image
source={require("@/assets/images/owner.png")}
style={styles.ownerLogo}
resizeMode="contain"
/>
</View>
<ThemedText style={styles.subtitle}> <ThemedText style={styles.subtitle}>
Đăng nhập đ tiếp tục Đăng nhập đ tiếp tục
</ThemedText> </ThemedText>
@@ -263,13 +255,6 @@ const styles = StyleSheet.create({
color: "#007AFF", color: "#007AFF",
fontWeight: "600", fontWeight: "600",
}, },
ownerContainer: {
alignItems: "center",
},
ownerLogo: {
width: 150,
height: 50,
},
copyrightContainer: { copyrightContainer: {
marginTop: 20, marginTop: 20,
alignItems: "center", alignItems: "center",

View File

@@ -1,6 +1,7 @@
import { IconSymbol } from "@/components/ui/icon-symbol"; import { IconSymbol } from "@/components/ui/icon-symbol";
import React, { useRef, useState } from "react"; import React, { useRef, useState } from "react";
import { Animated, Text, TouchableOpacity, View } from "react-native"; import { Animated, Text, TouchableOpacity, View } from "react-native";
import CrewDetailModal from "./modal/CrewDetailModal";
import styles from "./style/CrewListTable.styles"; import styles from "./style/CrewListTable.styles";
// --------------------------- // ---------------------------
@@ -11,6 +12,14 @@ interface CrewMember {
maDinhDanh: string; maDinhDanh: string;
ten: string; ten: string;
chucVu: string; chucVu: string;
ngaySinh?: string;
cccd?: string;
soDienThoai?: string;
diaChi?: string;
ngayVaoLam?: string;
trinhDoChuyenMon?: string;
bangCap?: string;
tinhTrang?: string;
} }
// --------------------------- // ---------------------------
@@ -22,21 +31,65 @@ const data: CrewMember[] = [
maDinhDanh: "ChuTau", maDinhDanh: "ChuTau",
ten: "Nguyễn Nhật Minh", ten: "Nguyễn Nhật Minh",
chucVu: "Chủ tàu", chucVu: "Chủ tàu",
ngaySinh: "08/06/2006",
cccd: "079085012345",
soDienThoai: "0912345678",
diaChi: "Hà Nội",
ngayVaoLam: "",
trinhDoChuyenMon: "Thuyền trưởng hạng I",
bangCap: "Bằng thuyền trưởng xa bờ",
tinhTrang: "Đang làm việc",
}, },
{ {
id: "1", id: "1",
maDinhDanh: "TV001", maDinhDanh: "TV001",
ten: "Nguyễn Văn A", ten: "Nguyễn Văn A",
chucVu: "Thuyền trưởng", chucVu: "Thuyền trưởng",
ngaySinh: "20/05/1988",
cccd: "079088011111",
soDienThoai: "0901234567",
diaChi: "456 Đường Cảng, Phường Thanh Khê, Đà Nẵng",
ngayVaoLam: "15/06/2015",
trinhDoChuyenMon: "Thuyền trưởng hạng II",
bangCap: "Bằng thuyền trưởng ven bờ",
tinhTrang: "Đang làm việc",
},
{
id: "2",
maDinhDanh: "TV002",
ten: "Trần Văn B",
chucVu: "Máy trưởng",
ngaySinh: "10/08/1990",
cccd: "079090022222",
soDienThoai: "0987654321",
diaChi: "789 Đường Nguyễn Văn Linh, Quận Sơn Trà, Đà Nẵng",
ngayVaoLam: "20/03/2016",
trinhDoChuyenMon: "Máy trưởng hạng III",
bangCap: "Bằng máy trưởng ven bờ",
tinhTrang: "Đang làm việc",
},
{
id: "3",
maDinhDanh: "TV003",
ten: "Lê Văn C",
chucVu: "Thủy thủ",
ngaySinh: "25/12/1995",
cccd: "079095033333",
soDienThoai: "0976543210",
diaChi: "321 Đường Hoàng Sa, Quận Ngũ Hành Sơn, Đà Nẵng",
ngayVaoLam: "10/07/2018",
trinhDoChuyenMon: "Thủy thủ hạng I",
bangCap: "Chứng chỉ thủy thủ",
tinhTrang: "Đang làm việc",
}, },
{ id: "2", maDinhDanh: "TV002", ten: "Trần Văn B", chucVu: "Máy trưởng" },
{ id: "3", maDinhDanh: "TV003", ten: "Lê Văn C", chucVu: "Thủy thủ" },
]; ];
const CrewListTable: React.FC = () => { const CrewListTable: React.FC = () => {
const [collapsed, setCollapsed] = useState(true); const [collapsed, setCollapsed] = useState(true);
const [contentHeight, setContentHeight] = useState<number>(0); const [contentHeight, setContentHeight] = useState<number>(0);
const animatedHeight = useRef(new Animated.Value(0)).current; const animatedHeight = useRef(new Animated.Value(0)).current;
const [modalVisible, setModalVisible] = useState(false);
const [selectedCrew, setSelectedCrew] = useState<CrewMember | null>(null);
const tongThanhVien = data.length; const tongThanhVien = data.length;
const handleToggle = () => { const handleToggle = () => {
@@ -50,7 +103,16 @@ const CrewListTable: React.FC = () => {
}; };
const handleCrewPress = (crewId: string) => { const handleCrewPress = (crewId: string) => {
console.log("Crew ID:", crewId); const crew = data.find((item) => item.id === crewId);
if (crew) {
setSelectedCrew(crew);
setModalVisible(true);
}
};
const handleCloseModal = () => {
setModalVisible(false);
setSelectedCrew(null);
}; };
return ( return (
@@ -157,6 +219,13 @@ const CrewListTable: React.FC = () => {
<Text style={[styles.cell, styles.right]}></Text> <Text style={[styles.cell, styles.right]}></Text>
</View> </View>
</Animated.View> </Animated.View>
{/* Modal chi tiết thuyền viên */}
<CrewDetailModal
visible={modalVisible}
onClose={handleCloseModal}
crewData={selectedCrew}
/>
</View> </View>
); );
}; };

View File

@@ -1,6 +1,7 @@
import { IconSymbol } from "@/components/ui/icon-symbol"; import { IconSymbol } from "@/components/ui/icon-symbol";
import React, { useRef, useState } from "react"; import React, { useRef, useState } from "react";
import { Animated, Text, TouchableOpacity, View } from "react-native"; import { Animated, Text, TouchableOpacity, View } from "react-native";
import TripCostDetailModal from "./modal/TripCostDetailModal";
import styles from "./style/TripCostTable.styles"; import styles from "./style/TripCostTable.styles";
// --------------------------- // ---------------------------
@@ -60,6 +61,7 @@ const data: CostItem[] = [
const TripCostTable: React.FC = () => { const TripCostTable: React.FC = () => {
const [collapsed, setCollapsed] = useState(true); const [collapsed, setCollapsed] = useState(true);
const [contentHeight, setContentHeight] = useState<number>(0); const [contentHeight, setContentHeight] = useState<number>(0);
const [modalVisible, setModalVisible] = useState(false);
const animatedHeight = useRef(new Animated.Value(0)).current; const animatedHeight = useRef(new Animated.Value(0)).current;
const tongCong = data.reduce((sum, item) => sum + item.tongChiPhi, 0); const tongCong = data.reduce((sum, item) => sum + item.tongChiPhi, 0);
@@ -74,7 +76,11 @@ const TripCostTable: React.FC = () => {
}; };
const handleViewDetail = () => { const handleViewDetail = () => {
console.log("View trip cost details"); setModalVisible(true);
};
const handleCloseModal = () => {
setModalVisible(false);
}; };
return ( return (
@@ -191,6 +197,13 @@ const TripCostTable: React.FC = () => {
<Text style={styles.viewDetailText}>Xem chi tiết</Text> <Text style={styles.viewDetailText}>Xem chi tiết</Text>
</TouchableOpacity> </TouchableOpacity>
</Animated.View> </Animated.View>
{/* Modal */}
<TripCostDetailModal
visible={modalVisible}
onClose={handleCloseModal}
data={data}
/>
</View> </View>
); );
}; };

View File

@@ -0,0 +1,91 @@
import { IconSymbol } from "@/components/ui/icon-symbol";
import React from "react";
import { Modal, ScrollView, Text, TouchableOpacity, View } from "react-native";
import styles from "./style/CrewDetailModal.styles";
// ---------------------------
// 🧩 Interface
// ---------------------------
interface CrewMember {
id: string;
maDinhDanh: string;
ten: string;
chucVu: string;
ngaySinh?: string;
cccd?: string;
soDienThoai?: string;
diaChi?: string;
ngayVaoLam?: string;
trinhDoChuyenMon?: string;
bangCap?: string;
tinhTrang?: string;
}
interface CrewDetailModalProps {
visible: boolean;
onClose: () => void;
crewData: CrewMember | null;
}
// ---------------------------
// 👤 Component Modal
// ---------------------------
const CrewDetailModal: React.FC<CrewDetailModalProps> = ({
visible,
onClose,
crewData,
}) => {
if (!crewData) return null;
const infoItems = [
{ label: "Mã định danh", value: crewData.maDinhDanh },
{ label: "Họ và tên", value: crewData.ten },
{ label: "Chức vụ", value: crewData.chucVu },
{ label: "Ngày sinh", value: crewData.ngaySinh || "Chưa cập nhật" },
{ label: "CCCD/CMND", value: crewData.cccd || "Chưa cập nhật" },
{ label: "Số điện thoại", value: crewData.soDienThoai || "Chưa cập nhật" },
{ label: "Địa chỉ", value: crewData.diaChi || "Chưa cập nhật" },
{ label: "Ngày vào làm", value: crewData.ngayVaoLam || "Chưa cập nhật" },
{
label: "Trình độ chuyên môn",
value: crewData.trinhDoChuyenMon || "Chưa cập nhật",
},
{ label: "Bằng cấp", value: crewData.bangCap || "Chưa cập nhật" },
{ label: "Tình trạng", value: crewData.tinhTrang || "Đang làm việc" },
];
return (
<Modal
visible={visible}
animationType="slide"
presentationStyle="pageSheet"
onRequestClose={onClose}
>
<View style={styles.container}>
{/* Header */}
<View style={styles.header}>
<Text style={styles.title}>Thông tin thuyền viên</Text>
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
<View style={styles.closeIconButton}>
<IconSymbol name="xmark" size={28} color="#fff" />
</View>
</TouchableOpacity>
</View>
{/* Content */}
<ScrollView style={styles.content}>
<View style={styles.infoCard}>
{infoItems.map((item, index) => (
<View key={index} style={styles.infoRow}>
<Text style={styles.infoLabel}>{item.label}</Text>
<Text style={styles.infoValue}>{item.value}</Text>
</View>
))}
</View>
</ScrollView>
</View>
</Modal>
);
};
export default CrewDetailModal;

View File

@@ -0,0 +1,222 @@
import { IconSymbol } from "@/components/ui/icon-symbol";
import React, { useState } from "react";
import {
KeyboardAvoidingView,
Modal,
Platform,
ScrollView,
Text,
TextInput,
TouchableOpacity,
View,
} from "react-native";
import styles from "./style/TripCostDetailModal.styles";
// ---------------------------
// 🧩 Interface
// ---------------------------
interface CostItem {
id: string;
loai: string;
soLuong: number;
donVi: string;
chiPhi: number;
tongChiPhi: number;
}
interface TripCostDetailModalProps {
visible: boolean;
onClose: () => void;
data: CostItem[];
}
// ---------------------------
// 💰 Component Modal
// ---------------------------
const TripCostDetailModal: React.FC<TripCostDetailModalProps> = ({
visible,
onClose,
data,
}) => {
const [isEditing, setIsEditing] = useState(false);
const [editableData, setEditableData] = useState<CostItem[]>(data);
const tongCong = editableData.reduce((sum, item) => sum + item.tongChiPhi, 0);
const handleEdit = () => {
setIsEditing(!isEditing);
};
const handleSave = () => {
setIsEditing(false);
// TODO: Save data to backend
console.log("Saved data:", editableData);
};
const handleCancel = () => {
setIsEditing(false);
setEditableData(data); // Reset to original data
};
const updateItem = (id: string, field: keyof CostItem, value: string) => {
setEditableData((prev) =>
prev.map((item) => {
if (item.id === id) {
const numValue =
field === "loai" || field === "donVi" ? value : Number(value) || 0;
const updated = { ...item, [field]: numValue };
// Recalculate tongChiPhi
if (field === "soLuong" || field === "chiPhi") {
updated.tongChiPhi = updated.soLuong * updated.chiPhi;
}
return updated;
}
return item;
})
);
};
return (
<Modal
visible={visible}
animationType="slide"
presentationStyle="pageSheet"
onRequestClose={onClose}
>
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior={Platform.OS === "ios" ? "padding" : "height"}
keyboardVerticalOffset={60}
>
<View style={styles.container}>
{/* Header */}
<View style={styles.header}>
<Text style={styles.title}>Chi tiết chi phí chuyến đi</Text>
<View style={styles.headerButtons}>
{isEditing ? (
<>
<TouchableOpacity
onPress={handleCancel}
style={styles.cancelButton}
>
<Text style={styles.cancelButtonText}>Hủy</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={handleSave}
style={styles.saveButton}
>
<Text style={styles.saveButtonText}>Lưu</Text>
</TouchableOpacity>
</>
) : (
<TouchableOpacity
onPress={handleEdit}
style={styles.editButton}
>
<View style={styles.editIconButton}>
<IconSymbol
name="pencil"
size={28}
color="#fff"
weight="heavy"
/>
</View>
</TouchableOpacity>
)}
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
<View style={styles.closeIconButton}>
<IconSymbol name="xmark" size={28} color="#fff" />
</View>
</TouchableOpacity>
</View>
</View>
{/* Content */}
<ScrollView style={styles.content}>
{editableData.map((item) => (
<View key={item.id} style={styles.itemCard}>
{/* Loại */}
<View style={styles.fieldGroup}>
<Text style={styles.label}>Loại chi phí</Text>
<TextInput
style={[styles.input, !isEditing && styles.inputDisabled]}
value={item.loai}
onChangeText={(value) => updateItem(item.id, "loai", value)}
editable={isEditing}
placeholder="Nhập loại chi phí"
/>
</View>
{/* Số lượng & Đơn vị */}
<View style={styles.rowGroup}>
<View
style={[styles.fieldGroup, { flex: 1, marginRight: 8 }]}
>
<Text style={styles.label}>Số lượng</Text>
<TextInput
style={[styles.input, !isEditing && styles.inputDisabled]}
value={String(item.soLuong)}
onChangeText={(value) =>
updateItem(item.id, "soLuong", value)
}
editable={isEditing}
keyboardType="numeric"
placeholder="0"
/>
</View>
<View style={[styles.fieldGroup, { flex: 1, marginLeft: 8 }]}>
<Text style={styles.label}>Đơn vị</Text>
<TextInput
style={[styles.input, !isEditing && styles.inputDisabled]}
value={item.donVi}
onChangeText={(value) =>
updateItem(item.id, "donVi", value)
}
editable={isEditing}
placeholder="kg, lít..."
/>
</View>
</View>
{/* Chi phí/đơn vị */}
<View style={styles.fieldGroup}>
<Text style={styles.label}>Chi phí/đơn vị (VNĐ)</Text>
<TextInput
style={[styles.input, !isEditing && styles.inputDisabled]}
value={String(item.chiPhi)}
onChangeText={(value) =>
updateItem(item.id, "chiPhi", value)
}
editable={isEditing}
keyboardType="numeric"
placeholder="0"
/>
</View>
{/* Tổng chi phí */}
<View style={styles.fieldGroup}>
<Text style={styles.label}>Tổng chi phí</Text>
<View style={styles.totalContainer}>
<Text style={styles.totalText}>
{item.tongChiPhi.toLocaleString()} VNĐ
</Text>
</View>
</View>
</View>
))}
{/* Footer Total */}
<View style={styles.footerTotal}>
<Text style={styles.footerLabel}>Tổng cộng</Text>
<Text style={styles.footerAmount}>
{tongCong.toLocaleString()} VNĐ
</Text>
</View>
</ScrollView>
</View>
</KeyboardAvoidingView>
</Modal>
);
};
export default TripCostDetailModal;

View File

@@ -0,0 +1,69 @@
import { StyleSheet } from "react-native";
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#f5f5f5",
},
header: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 20,
paddingTop: 30,
paddingBottom: 16,
backgroundColor: "#fff",
borderBottomWidth: 1,
borderBottomColor: "#eee",
},
title: {
fontSize: 22,
fontWeight: "700",
color: "#000",
flex: 1,
},
closeButton: {
padding: 4,
},
closeIconButton: {
backgroundColor: "#FF3B30",
borderRadius: 10,
padding: 10,
justifyContent: "center",
alignItems: "center",
},
content: {
flex: 1,
padding: 16,
marginBottom: 15,
},
infoCard: {
backgroundColor: "#fff",
borderRadius: 12,
padding: 16,
marginBottom: 20,
shadowColor: "#000",
shadowOpacity: 0.05,
shadowRadius: 4,
shadowOffset: { width: 0, height: 2 },
elevation: 2,
},
infoRow: {
paddingVertical: 12,
borderBottomWidth: 1,
borderBottomColor: "#f0f0f0",
},
infoLabel: {
fontSize: 13,
fontWeight: "600",
color: "#666",
marginBottom: 6,
},
infoValue: {
fontSize: 16,
color: "#000",
fontWeight: "500",
},
});
export default styles;

View File

@@ -0,0 +1,153 @@
import { StyleSheet } from "react-native";
const styles = StyleSheet.create({
closeIconButton: {
backgroundColor: "#FF3B30",
borderRadius: 10,
padding: 10,
justifyContent: "center",
alignItems: "center",
},
container: {
flex: 1,
backgroundColor: "#f5f5f5",
},
header: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 20,
paddingTop: 30,
paddingBottom: 16,
backgroundColor: "#fff",
borderBottomWidth: 1,
borderBottomColor: "#eee",
},
title: {
fontSize: 22,
fontWeight: "700",
color: "#000",
flex: 1,
},
headerButtons: {
flexDirection: "row",
alignItems: "center",
gap: 12,
},
editButton: {
padding: 4,
},
editIconButton: {
backgroundColor: "#007AFF",
borderRadius: 10,
padding: 10,
justifyContent: "center",
alignItems: "center",
},
cancelButton: {
paddingHorizontal: 12,
paddingVertical: 6,
},
cancelButtonText: {
color: "#007AFF",
fontSize: 16,
fontWeight: "600",
},
saveButton: {
backgroundColor: "#007AFF",
paddingHorizontal: 16,
paddingVertical: 6,
borderRadius: 6,
},
saveButtonText: {
color: "#fff",
fontSize: 16,
fontWeight: "600",
},
closeButton: {
padding: 4,
},
content: {
flex: 1,
padding: 16,
},
itemCard: {
backgroundColor: "#fff",
borderRadius: 12,
padding: 16,
marginBottom: 12,
shadowColor: "#000",
shadowOpacity: 0.05,
shadowRadius: 4,
shadowOffset: { width: 0, height: 2 },
elevation: 2,
},
fieldGroup: {
marginBottom: 12,
},
rowGroup: {
flexDirection: "row",
marginBottom: 12,
},
label: {
fontSize: 13,
fontWeight: "600",
color: "#666",
marginBottom: 6,
},
input: {
borderWidth: 1,
borderColor: "#007AFF",
borderRadius: 8,
paddingHorizontal: 12,
paddingVertical: 10,
fontSize: 15,
color: "#000",
backgroundColor: "#fff",
},
inputDisabled: {
borderColor: "#ddd",
backgroundColor: "#f9f9f9",
color: "#666",
},
totalContainer: {
backgroundColor: "#fff5e6",
borderRadius: 8,
paddingHorizontal: 12,
paddingVertical: 10,
borderWidth: 1,
borderColor: "#ffd699",
},
totalText: {
fontSize: 16,
fontWeight: "700",
color: "#ff6600",
},
footerTotal: {
backgroundColor: "#fff",
borderRadius: 12,
padding: 20,
marginTop: 8,
marginBottom: 50,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
shadowColor: "#000",
shadowOpacity: 0.1,
shadowRadius: 4,
shadowOffset: { width: 0, height: 2 },
elevation: 3,
},
footerLabel: {
fontSize: 18,
fontWeight: "700",
color: "#007bff",
},
footerAmount: {
fontSize: 20,
fontWeight: "700",
color: "#ff6600",
},
});
export default styles;

View File

@@ -28,6 +28,8 @@ const MAPPING = {
"exclamationmark.triangle.fill": "warning", "exclamationmark.triangle.fill": "warning",
"book.closed.fill": "book", "book.closed.fill": "book",
"dot.radiowaves.left.and.right": "sensors", "dot.radiowaves.left.and.right": "sensors",
xmark: "close",
pencil: "edit",
} as IconMapping; } as IconMapping;
/** /**

25
package-lock.json generated
View File

@@ -31,6 +31,7 @@
"react-dom": "19.1.0", "react-dom": "19.1.0",
"react-native": "0.81.5", "react-native": "0.81.5",
"react-native-gesture-handler": "~2.28.0", "react-native-gesture-handler": "~2.28.0",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
"react-native-maps": "^1.20.1", "react-native-maps": "^1.20.1",
"react-native-reanimated": "~4.1.1", "react-native-reanimated": "~4.1.1",
"react-native-safe-area-context": "5.4.0", "react-native-safe-area-context": "5.4.0",
@@ -10817,7 +10818,6 @@
"version": "15.8.1", "version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"loose-envify": "^1.4.0", "loose-envify": "^1.4.0",
@@ -10829,7 +10829,6 @@
"version": "16.13.1", "version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/proxy-from-env": { "node_modules/proxy-from-env": {
@@ -11345,6 +11344,15 @@
"react-native": "*" "react-native": "*"
} }
}, },
"node_modules/react-native-iphone-x-helper": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.3.1.tgz",
"integrity": "sha512-HOf0jzRnq2/aFUcdCJ9w9JGzN3gdEg0zFE4FyYlp4jtidqU03D5X7ZegGKfT1EWteR0gPBGp9ye5T5FvSWi9Yg==",
"license": "MIT",
"peerDependencies": {
"react-native": ">=0.42.0"
}
},
"node_modules/react-native-is-edge-to-edge": { "node_modules/react-native-is-edge-to-edge": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.2.1.tgz", "resolved": "https://registry.npmjs.org/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.2.1.tgz",
@@ -11355,6 +11363,19 @@
"react-native": "*" "react-native": "*"
} }
}, },
"node_modules/react-native-keyboard-aware-scroll-view": {
"version": "0.9.5",
"resolved": "https://registry.npmjs.org/react-native-keyboard-aware-scroll-view/-/react-native-keyboard-aware-scroll-view-0.9.5.tgz",
"integrity": "sha512-XwfRn+T/qBH9WjTWIBiJD2hPWg0yJvtaEw6RtPCa5/PYHabzBaWxYBOl0usXN/368BL1XktnZPh8C2lmTpOREA==",
"license": "MIT",
"dependencies": {
"prop-types": "^15.6.2",
"react-native-iphone-x-helper": "^1.0.3"
},
"peerDependencies": {
"react-native": ">=0.48.4"
}
},
"node_modules/react-native-maps": { "node_modules/react-native-maps": {
"version": "1.20.1", "version": "1.20.1",
"resolved": "https://registry.npmjs.org/react-native-maps/-/react-native-maps-1.20.1.tgz", "resolved": "https://registry.npmjs.org/react-native-maps/-/react-native-maps-1.20.1.tgz",

View File

@@ -34,6 +34,7 @@
"react-dom": "19.1.0", "react-dom": "19.1.0",
"react-native": "0.81.5", "react-native": "0.81.5",
"react-native-gesture-handler": "~2.28.0", "react-native-gesture-handler": "~2.28.0",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
"react-native-maps": "^1.20.1", "react-native-maps": "^1.20.1",
"react-native-reanimated": "~4.1.1", "react-native-reanimated": "~4.1.1",
"react-native-safe-area-context": "5.4.0", "react-native-safe-area-context": "5.4.0",