thêm FormSearch trong map
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
import DraggablePanel from "@/components/DraggablePanel";
|
||||
import IconButton from "@/components/IconButton";
|
||||
import type { PolygonWithLabelProps } from "@/components/map/PolygonWithLabel";
|
||||
import type { PolylineWithLabelProps } from "@/components/map/PolylineWithLabel";
|
||||
import ShipInfo from "@/components/map/ShipInfo";
|
||||
import { TagState, TagStateCallbackPayload } from "@/components/map/TagState";
|
||||
import ShipSearchForm, {
|
||||
SearchShipResponse,
|
||||
} from "@/components/ShipSearchForm";
|
||||
import { EVENT_SEARCH_THINGS, IOS_PLATFORM, LIGHT_THEME } from "@/constants";
|
||||
import { usePlatform } from "@/hooks/use-platform";
|
||||
import { useThemeContext } from "@/hooks/use-theme-context";
|
||||
import { searchThingEventBus } from "@/services/device_events";
|
||||
import { getShipIcon } from "@/services/map_service";
|
||||
import eventBus from "@/utils/eventBus";
|
||||
import { AntDesign } from "@expo/vector-icons";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
Animated,
|
||||
@@ -36,15 +41,34 @@ export default function HomeScreen() {
|
||||
const [polygonCoordinates, setPolygonCoordinates] = useState<
|
||||
PolygonWithLabelProps[]
|
||||
>([]);
|
||||
const [shipSearchFormOpen, setShipSearchFormOpen] = useState(false);
|
||||
const [isPanelExpanded, setIsPanelExpanded] = useState(false);
|
||||
const [things, setThings] = useState<Model.ThingsResponse | null>(null);
|
||||
const platform = usePlatform();
|
||||
const theme = useThemeContext().colorScheme;
|
||||
const scale = useRef(new Animated.Value(0)).current;
|
||||
const opacity = useRef(new Animated.Value(1)).current;
|
||||
const [shipSearchFormData, setShipSearchFormData] = useState<
|
||||
SearchShipResponse | undefined
|
||||
>(undefined);
|
||||
const [tagStatePayload, setTagStatePayload] =
|
||||
useState<TagStateCallbackPayload | null>(null);
|
||||
|
||||
// Thêm state để quản lý tracksViewChanges
|
||||
const [tracksViewChanges, setTracksViewChanges] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (tagStatePayload) {
|
||||
searchThings();
|
||||
}
|
||||
}, [tagStatePayload]);
|
||||
|
||||
useEffect(() => {
|
||||
if (shipSearchFormData) {
|
||||
searchThings();
|
||||
}
|
||||
}, [shipSearchFormData]);
|
||||
|
||||
const bodySearchThings: Model.SearchThingBody = {
|
||||
offset: 0,
|
||||
limit: 50,
|
||||
@@ -176,6 +200,7 @@ export default function HomeScreen() {
|
||||
// }, [banzoneData, entityData]);
|
||||
|
||||
// Hàm tính radius cố định khi zoom change
|
||||
|
||||
const calculateRadiusFromZoom = (zoom: number) => {
|
||||
const baseZoom = 10;
|
||||
const baseRadius = 100;
|
||||
@@ -231,37 +256,39 @@ export default function HomeScreen() {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (alarmData?.level === 3) {
|
||||
const loop = Animated.loop(
|
||||
Animated.sequence([
|
||||
Animated.parallel([
|
||||
Animated.timing(scale, {
|
||||
toValue: 3, // nở to 3 lần
|
||||
duration: 1500,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
Animated.timing(opacity, {
|
||||
toValue: 0, // mờ dần
|
||||
duration: 1500,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
]),
|
||||
Animated.parallel([
|
||||
Animated.timing(scale, {
|
||||
toValue: 0,
|
||||
duration: 0,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
Animated.timing(opacity, {
|
||||
toValue: 1,
|
||||
duration: 0,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
]),
|
||||
])
|
||||
);
|
||||
loop.start();
|
||||
return () => loop.stop();
|
||||
for (var thing of things?.things || []) {
|
||||
if (thing.metadata?.state_level === 3) {
|
||||
const loop = Animated.loop(
|
||||
Animated.sequence([
|
||||
Animated.parallel([
|
||||
Animated.timing(scale, {
|
||||
toValue: 3, // nở to 3 lần
|
||||
duration: 1500,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
Animated.timing(opacity, {
|
||||
toValue: 0, // mờ dần
|
||||
duration: 1500,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
]),
|
||||
Animated.parallel([
|
||||
Animated.timing(scale, {
|
||||
toValue: 0,
|
||||
duration: 0,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
Animated.timing(opacity, {
|
||||
toValue: 1,
|
||||
duration: 0,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
]),
|
||||
])
|
||||
);
|
||||
loop.start();
|
||||
return () => loop.stop();
|
||||
}
|
||||
}
|
||||
}, [things, scale, opacity]);
|
||||
|
||||
@@ -276,26 +303,78 @@ export default function HomeScreen() {
|
||||
}
|
||||
}, [isFirstLoad]);
|
||||
|
||||
const handleOnPressState = (state: TagStateCallbackPayload) => {
|
||||
const searchThings = async () => {
|
||||
console.log("FormSearch Playload in Search Thing: ", shipSearchFormData);
|
||||
|
||||
// Xây dựng query state dựa trên logic bạn cung cấp
|
||||
const stateNormalQuery = state.isNormal ? "normal" : "";
|
||||
const stateSosQuery = state.isSos ? "sos" : "";
|
||||
const stateWarningQuery = state.isWarning
|
||||
const stateNormalQuery = tagStatePayload?.isNormal ? "normal" : "";
|
||||
const stateSosQuery = tagStatePayload?.isSos ? "sos" : "";
|
||||
const stateWarningQuery = tagStatePayload?.isWarning
|
||||
? stateNormalQuery + ",warning"
|
||||
: stateNormalQuery;
|
||||
const stateCriticalQuery = state.isDangerous
|
||||
const stateCriticalQuery = tagStatePayload?.isDangerous
|
||||
? stateWarningQuery + ",critical"
|
||||
: stateWarningQuery;
|
||||
|
||||
// Nếu bật tất cả filter thì không cần truyền stateQuery
|
||||
const stateQuery =
|
||||
state.isNormal && state.isWarning && state.isDangerous && state.isSos
|
||||
tagStatePayload?.isNormal &&
|
||||
tagStatePayload?.isWarning &&
|
||||
tagStatePayload?.isDangerous &&
|
||||
tagStatePayload?.isSos
|
||||
? ""
|
||||
: [stateCriticalQuery, stateSosQuery].filter(Boolean).join(",");
|
||||
let metaFormQuery = {};
|
||||
if (state.isDisconected)
|
||||
if (tagStatePayload?.isDisconected)
|
||||
metaFormQuery = { ...metaFormQuery, connected: false };
|
||||
|
||||
if (shipSearchFormData?.ship_name) {
|
||||
metaFormQuery = {
|
||||
...metaFormQuery,
|
||||
ship_name: shipSearchFormData?.ship_name,
|
||||
};
|
||||
}
|
||||
if (shipSearchFormData?.reg_number) {
|
||||
metaFormQuery = {
|
||||
...metaFormQuery,
|
||||
reg_number: shipSearchFormData?.reg_number,
|
||||
};
|
||||
}
|
||||
if (
|
||||
shipSearchFormData?.ship_length[0] !== 0 ||
|
||||
shipSearchFormData?.ship_length[1] !== 100
|
||||
) {
|
||||
metaFormQuery = {
|
||||
...metaFormQuery,
|
||||
ship_length: shipSearchFormData?.ship_length,
|
||||
};
|
||||
}
|
||||
if (
|
||||
shipSearchFormData?.ship_power[0] !== 0 ||
|
||||
shipSearchFormData?.ship_power[1] !== 100000
|
||||
) {
|
||||
metaFormQuery = {
|
||||
...metaFormQuery,
|
||||
ship_power: shipSearchFormData?.ship_power,
|
||||
};
|
||||
}
|
||||
if (shipSearchFormData?.alarm_list) {
|
||||
metaFormQuery = {
|
||||
...metaFormQuery,
|
||||
alarm_list: shipSearchFormData?.alarm_list,
|
||||
};
|
||||
}
|
||||
if (shipSearchFormData?.ship_type) {
|
||||
metaFormQuery = {
|
||||
...metaFormQuery,
|
||||
ship_type: shipSearchFormData?.ship_type,
|
||||
};
|
||||
}
|
||||
if (shipSearchFormData?.ship_group_id) {
|
||||
metaFormQuery = {
|
||||
...metaFormQuery,
|
||||
ship_group_id: shipSearchFormData?.ship_group_id,
|
||||
};
|
||||
}
|
||||
// Tạo metadata query
|
||||
const metaStateQuery =
|
||||
stateQuery !== "" ? { state_level: stateQuery } : null;
|
||||
@@ -312,10 +391,28 @@ export default function HomeScreen() {
|
||||
not_empty: "ship_id",
|
||||
},
|
||||
};
|
||||
console.log("Search Params: ", searchParams);
|
||||
|
||||
// Gọi API tìm kiếm
|
||||
searchThingEventBus(searchParams);
|
||||
};
|
||||
const handleOnSubmitSearchForm = async (data: SearchShipResponse) => {
|
||||
setShipSearchFormData(data);
|
||||
setShipSearchFormOpen(false);
|
||||
};
|
||||
|
||||
const hasActiveFilters = shipSearchFormData
|
||||
? shipSearchFormData.ship_name !== "" ||
|
||||
shipSearchFormData.reg_number !== "" ||
|
||||
shipSearchFormData.ship_length[0] !== 0 ||
|
||||
shipSearchFormData.ship_length[1] !== 100 ||
|
||||
shipSearchFormData.ship_power[0] !== 0 ||
|
||||
shipSearchFormData.ship_power[1] !== 100000 ||
|
||||
shipSearchFormData.ship_type !== "" ||
|
||||
shipSearchFormData.alarm_list !== "" ||
|
||||
shipSearchFormData.ship_group_id !== "" ||
|
||||
shipSearchFormData.group_id !== ""
|
||||
: false;
|
||||
|
||||
return (
|
||||
<GestureHandlerRootView style={styles.container}>
|
||||
@@ -411,7 +508,20 @@ export default function HomeScreen() {
|
||||
</>
|
||||
)}
|
||||
</MapView>
|
||||
|
||||
<View className="absolute top-20 left-5">
|
||||
{!isPanelExpanded && (
|
||||
<IconButton
|
||||
icon={<AntDesign name="filter" size={16} />}
|
||||
type="primary"
|
||||
size="large"
|
||||
style={{
|
||||
borderRadius: 10,
|
||||
backgroundColor: hasActiveFilters ? "#B8D576" : "#fff",
|
||||
}}
|
||||
onPress={() => setShipSearchFormOpen(true)}
|
||||
></IconButton>
|
||||
)}
|
||||
</View>
|
||||
{/* <View className="absolute top-14 right-2 shadow-md">
|
||||
<SosButton />
|
||||
</View>
|
||||
@@ -420,10 +530,11 @@ export default function HomeScreen() {
|
||||
{/* Draggable Panel */}
|
||||
<DraggablePanel
|
||||
minHeightPct={0.1}
|
||||
maxHeightPct={0.5}
|
||||
maxHeightPct={0.6}
|
||||
initialState="min"
|
||||
onExpandedChange={(expanded) => {
|
||||
console.log("Panel expanded:", expanded);
|
||||
setIsPanelExpanded(expanded);
|
||||
}}
|
||||
>
|
||||
<>
|
||||
@@ -437,22 +548,44 @@ export default function HomeScreen() {
|
||||
(things?.metadata?.total_thing ?? 0) -
|
||||
(things?.metadata?.total_connected ?? 0) || 0
|
||||
}
|
||||
onTagPress={handleOnPressState}
|
||||
onTagPress={(tagState) => {
|
||||
setTagStatePayload(tagState);
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
<View style={{ width: "100%", paddingVertical: 8, flex: 1 }}>
|
||||
<Text
|
||||
style={{ fontSize: 20, textAlign: "center", fontWeight: "600" }}
|
||||
>
|
||||
Danh sách tàu thuyền
|
||||
</Text>
|
||||
<View className="flex flex-row items-center">
|
||||
<View className="flex-1 justify-center">
|
||||
<Text
|
||||
style={{
|
||||
fontSize: 20,
|
||||
textAlign: "center",
|
||||
fontWeight: "600",
|
||||
}}
|
||||
>
|
||||
Danh sách tàu thuyền
|
||||
</Text>
|
||||
</View>
|
||||
{isPanelExpanded && (
|
||||
<IconButton
|
||||
icon={<AntDesign name="filter" size={16} />}
|
||||
type="primary"
|
||||
shape="circle"
|
||||
size="middle"
|
||||
style={{
|
||||
// borderRadius: 10,
|
||||
backgroundColor: hasActiveFilters ? "#B8D576" : "#fff",
|
||||
}}
|
||||
onPress={() => setShipSearchFormOpen(true)}
|
||||
></IconButton>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<ScrollView
|
||||
style={{ width: "100%", marginTop: 8, flex: 1 }}
|
||||
contentContainerStyle={{
|
||||
alignItems: "center",
|
||||
paddingBottom: 24,
|
||||
// backgroundColor: "green",
|
||||
}}
|
||||
showsVerticalScrollIndicator={false}
|
||||
>
|
||||
@@ -485,6 +618,12 @@ export default function HomeScreen() {
|
||||
</View>
|
||||
</>
|
||||
</DraggablePanel>
|
||||
<ShipSearchForm
|
||||
initialValues={shipSearchFormData}
|
||||
isOpen={shipSearchFormOpen}
|
||||
onClose={() => setShipSearchFormOpen(false)}
|
||||
onSubmit={handleOnSubmitSearchForm}
|
||||
/>
|
||||
</View>
|
||||
</GestureHandlerRootView>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user