Compare commits
1 Commits
api-donati
...
api-maps/1
| Author | SHA1 | Date | |
|---|---|---|---|
| f750d158be |
@@ -1,54 +1,226 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BaseBox,
|
|
||||||
BoxButtonOnFooter,
|
BoxButtonOnFooter,
|
||||||
ButtonCenteredOnly,
|
ButtonCenteredOnly,
|
||||||
ButtonCustom,
|
ButtonCustom,
|
||||||
InformationBox,
|
InformationBox,
|
||||||
LandscapeFrameUploaded,
|
LandscapeFrameUploaded,
|
||||||
MapCustom,
|
|
||||||
Spacing,
|
Spacing,
|
||||||
TextInputCustom,
|
TextInputCustom,
|
||||||
ViewWrapper
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import API_IMAGE from "@/constants/api-storage";
|
||||||
|
import DIRECTORY_ID from "@/constants/directory-id";
|
||||||
|
import { apiMapsGetOne, apiMapsUpdate } from "@/service/api-client/api-maps";
|
||||||
|
import { uploadFileService } from "@/service/upload-service";
|
||||||
|
import pickFile, { IFileData } from "@/utils/pickFile";
|
||||||
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
import { StyleSheet, View } from "react-native";
|
||||||
|
import MapView, { LatLng, Marker } from "react-native-maps";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
|
const defaultRegion = {
|
||||||
|
latitude: -8.737109,
|
||||||
|
longitude: 115.1756897,
|
||||||
|
latitudeDelta: 0.1,
|
||||||
|
longitudeDelta: 0.1,
|
||||||
|
};
|
||||||
export default function MapsEdit() {
|
export default function MapsEdit() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
|
const [data, setData] = useState<any | null>({
|
||||||
|
id: "",
|
||||||
|
namePin: "",
|
||||||
|
latitude: "",
|
||||||
|
longitude: "",
|
||||||
|
imageId: "",
|
||||||
|
});
|
||||||
|
const [selectedLocation, setSelectedLocation] = useState<LatLng | null>(null);
|
||||||
|
const [image, setImage] = useState<IFileData | null>(null);
|
||||||
|
const [isLoading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiMapsGetOne({ id: id as string });
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setData({
|
||||||
|
id: response.data.id,
|
||||||
|
namePin: response.data.namePin,
|
||||||
|
latitude: response.data.latitude,
|
||||||
|
longitude: response.data.longitude,
|
||||||
|
imageId: response.data.imageId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMapPress = (event: any) => {
|
||||||
|
const { latitude, longitude } = event.nativeEvent.coordinate;
|
||||||
|
const location = { latitude, longitude };
|
||||||
|
setSelectedLocation(location);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
let newData: any;
|
||||||
|
if (!data.namePin) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Nama pin harus diisi",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
newData = {
|
||||||
|
namePin: data?.namePin,
|
||||||
|
latitude: selectedLocation?.latitude || data?.latitude,
|
||||||
|
longitude: selectedLocation?.longitude || data?.longitude,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
if (image) {
|
||||||
|
const responseUpload = await uploadFileService({
|
||||||
|
dirId: DIRECTORY_ID.map_image,
|
||||||
|
imageUri: image?.uri,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!responseUpload?.data?.id) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal mengunggah gambar",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageId = responseUpload?.data?.id;
|
||||||
|
|
||||||
|
newData = {
|
||||||
|
namePin: data?.namePin,
|
||||||
|
latitude: selectedLocation?.latitude,
|
||||||
|
longitude: selectedLocation?.longitude,
|
||||||
|
newImageId: imageId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const responseUpdate = await apiMapsUpdate({
|
||||||
|
id: data?.id,
|
||||||
|
data: newData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!responseUpdate.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal mengupdate map",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Map berhasil diupdate",
|
||||||
|
});
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const buttonFooter = (
|
const buttonFooter = (
|
||||||
<BoxButtonOnFooter>
|
<BoxButtonOnFooter>
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
onPress={() => {
|
disabled={!data.namePin}
|
||||||
console.log(`Simpan maps ${id}`);
|
onPress={handleSubmit}
|
||||||
router.back()
|
isLoading={isLoading}
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Simpan
|
Update
|
||||||
</ButtonCustom>
|
</ButtonCustom>
|
||||||
</BoxButtonOnFooter>
|
</BoxButtonOnFooter>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewWrapper footerComponent={buttonFooter}>
|
<ViewWrapper footerComponent={buttonFooter}>
|
||||||
<InformationBox text="Tentukan lokasi pin map dengan menekan pada map." />
|
<InformationBox text="Tentukan lokasi pin map dengan menekan pada map." />
|
||||||
|
|
||||||
<BaseBox>
|
<View style={[styles.container, { height: 400 }]}>
|
||||||
<MapCustom />
|
<MapView
|
||||||
</BaseBox>
|
style={styles.map}
|
||||||
|
initialRegion={
|
||||||
|
data?.latitude && data?.longitude
|
||||||
|
? {
|
||||||
|
latitude: data?.latitude,
|
||||||
|
longitude: data?.longitude,
|
||||||
|
latitudeDelta: 0.1,
|
||||||
|
longitudeDelta: 0.1,
|
||||||
|
}
|
||||||
|
: defaultRegion
|
||||||
|
}
|
||||||
|
onPress={handleMapPress}
|
||||||
|
showsUserLocation={true}
|
||||||
|
showsMyLocationButton={true}
|
||||||
|
loadingEnabled={true}
|
||||||
|
loadingIndicatorColor="#666"
|
||||||
|
loadingBackgroundColor="#f0f0f0"
|
||||||
|
>
|
||||||
|
{selectedLocation ? (
|
||||||
|
<Marker
|
||||||
|
coordinate={selectedLocation}
|
||||||
|
title="Lokasi Dipilih"
|
||||||
|
description={`Lat: ${selectedLocation.latitude.toFixed(
|
||||||
|
6
|
||||||
|
)}, Lng: ${selectedLocation.longitude.toFixed(6)}`}
|
||||||
|
pinColor="red"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Marker
|
||||||
|
coordinate={defaultRegion}
|
||||||
|
title="Lokasi Dipilih"
|
||||||
|
description={`Lat: ${defaultRegion.latitude.toFixed(
|
||||||
|
6
|
||||||
|
)}, Lng: ${defaultRegion.longitude.toFixed(6)}`}
|
||||||
|
pinColor="red"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</MapView>
|
||||||
|
</View>
|
||||||
|
|
||||||
<TextInputCustom
|
<TextInputCustom
|
||||||
required
|
required
|
||||||
label="Nama Pin"
|
label="Nama Pin"
|
||||||
placeholder="Masukkan nama pin maps"
|
placeholder="Masukkan nama pin maps"
|
||||||
|
value={data?.namePin}
|
||||||
|
onChangeText={(value) => setData({ ...data, namePin: value })}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Spacing />
|
<Spacing />
|
||||||
|
|
||||||
<InformationBox text="Upload foto lokasi bisnis anda untuk ditampilkan dalam detail maps." />
|
<InformationBox text="Upload foto lokasi bisnis anda untuk ditampilkan dalam detail maps." />
|
||||||
<LandscapeFrameUploaded />
|
<LandscapeFrameUploaded
|
||||||
|
image={
|
||||||
|
image
|
||||||
|
? image?.uri
|
||||||
|
: API_IMAGE.GET({ fileId: data?.imageId as string })
|
||||||
|
}
|
||||||
|
/>
|
||||||
<ButtonCenteredOnly
|
<ButtonCenteredOnly
|
||||||
icon="upload"
|
icon="upload"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
console.log("Upload foto ");
|
pickFile({
|
||||||
router.navigate(`/take-picture/${id}`);
|
allowedType: "image",
|
||||||
|
setImageUri(file) {
|
||||||
|
setImage(file);
|
||||||
|
},
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Upload
|
Upload
|
||||||
@@ -57,3 +229,16 @@ export default function MapsEdit() {
|
|||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
width: "100%",
|
||||||
|
backgroundColor: "#f5f5f5",
|
||||||
|
overflow: "hidden",
|
||||||
|
borderRadius: 8,
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
map: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@@ -6,21 +6,96 @@ import {
|
|||||||
InformationBox,
|
InformationBox,
|
||||||
LandscapeFrameUploaded,
|
LandscapeFrameUploaded,
|
||||||
Spacing,
|
Spacing,
|
||||||
TextCustom,
|
|
||||||
TextInputCustom,
|
TextInputCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
|
import MapSelected from "@/components/Map/MapSelected";
|
||||||
|
import DIRECTORY_ID from "@/constants/directory-id";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
import { apiMapsCreate } from "@/service/api-client/api-maps";
|
||||||
|
import { uploadFileService } from "@/service/upload-service";
|
||||||
|
import pickFile, { IFileData } from "@/utils/pickFile";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { LatLng } from "react-native-maps";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function MapsCreate() {
|
export default function MapsCreate() {
|
||||||
|
const { user } = useAuth();
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
|
const [selectedLocation, setSelectedLocation] = useState<LatLng | null>(null);
|
||||||
|
const [name, setName] = useState<string>("");
|
||||||
|
const [image, setImage] = useState<IFileData | null>(null);
|
||||||
|
const [isLoading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
let newData: any;
|
||||||
|
newData = {
|
||||||
|
authorId: user?.id,
|
||||||
|
portofolioId: id,
|
||||||
|
namePin: name,
|
||||||
|
latitude: selectedLocation?.latitude,
|
||||||
|
longitude: selectedLocation?.longitude,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (image) {
|
||||||
|
const responseUpload = await uploadFileService({
|
||||||
|
dirId: DIRECTORY_ID.map_image,
|
||||||
|
imageUri: image?.uri,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!responseUpload?.data?.id) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal mengunggah gambar",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageId = responseUpload?.data?.id;
|
||||||
|
|
||||||
|
newData = {
|
||||||
|
authorId: user?.id,
|
||||||
|
portofolioId: id,
|
||||||
|
namePin: name,
|
||||||
|
latitude: selectedLocation?.latitude,
|
||||||
|
longitude: selectedLocation?.longitude,
|
||||||
|
imageId: imageId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await apiMapsCreate({
|
||||||
|
data: newData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal menambahkan map",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Map berhasil ditambahkan",
|
||||||
|
});
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const buttonFooter = (
|
const buttonFooter = (
|
||||||
<BoxButtonOnFooter>
|
<BoxButtonOnFooter>
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
onPress={() => {
|
isLoading={isLoading}
|
||||||
console.log(`Simpan maps ${id}`);
|
disabled={!selectedLocation || name === ""}
|
||||||
router.replace(`/portofolio/${id}`);
|
onPress={handleSubmit}
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Simpan
|
Simpan
|
||||||
</ButtonCustom>
|
</ButtonCustom>
|
||||||
@@ -30,25 +105,34 @@ export default function MapsCreate() {
|
|||||||
<ViewWrapper footerComponent={buttonFooter}>
|
<ViewWrapper footerComponent={buttonFooter}>
|
||||||
<InformationBox text="Tentukan lokasi pin map dengan menekan pada map." />
|
<InformationBox text="Tentukan lokasi pin map dengan menekan pada map." />
|
||||||
|
|
||||||
<BaseBox style={{ height: 400 }}>
|
<BaseBox>
|
||||||
<TextCustom>Maps Her</TextCustom>
|
<MapSelected
|
||||||
|
selectedLocation={selectedLocation as any}
|
||||||
|
setSelectedLocation={setSelectedLocation}
|
||||||
|
/>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
|
|
||||||
<TextInputCustom
|
<TextInputCustom
|
||||||
required
|
required
|
||||||
label="Nama Pin"
|
label="Nama Pin"
|
||||||
placeholder="Masukkan nama pin maps"
|
placeholder="Masukkan nama pin maps"
|
||||||
|
value={name}
|
||||||
|
onChangeText={setName}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Spacing height={50} />
|
<Spacing height={50} />
|
||||||
|
|
||||||
<InformationBox text="Upload foto lokasi bisnis anda untuk ditampilkan dalam detail maps." />
|
<InformationBox text="Upload foto lokasi bisnis anda untuk ditampilkan dalam detail maps." />
|
||||||
<LandscapeFrameUploaded />
|
<LandscapeFrameUploaded image={image?.uri} />
|
||||||
<ButtonCenteredOnly
|
<ButtonCenteredOnly
|
||||||
icon="upload"
|
icon="upload"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
console.log("Upload foto ");
|
pickFile({
|
||||||
router.navigate(`/take-picture/${id}`);
|
allowedType: "image",
|
||||||
|
setImageUri(file) {
|
||||||
|
setImage(file);
|
||||||
|
},
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Upload
|
Upload
|
||||||
|
|||||||
@@ -1,19 +1,234 @@
|
|||||||
import { MapCustom, ViewWrapper } from "@/components";
|
import {
|
||||||
|
ButtonCustom,
|
||||||
|
DrawerCustom,
|
||||||
|
DummyLandscapeImage,
|
||||||
|
Grid,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import GridTwoView from "@/components/_ShareComponent/GridTwoView";
|
||||||
|
import API_IMAGE from "@/constants/api-storage";
|
||||||
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
|
import { apiMapsGetAll } from "@/service/api-client/api-maps";
|
||||||
|
import { openInDeviceMaps } from "@/utils/openInDeviceMaps";
|
||||||
|
import { FontAwesome, Ionicons } from "@expo/vector-icons";
|
||||||
|
import { Image } from "expo-image";
|
||||||
|
import { router, useFocusEffect } from "expo-router";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
import MapView from "react-native-maps";
|
import MapView, { Marker } from "react-native-maps";
|
||||||
|
|
||||||
|
const defaultRegion = {
|
||||||
|
latitude: -8.737109,
|
||||||
|
longitude: 115.1756897,
|
||||||
|
latitudeDelta: 0.1,
|
||||||
|
longitudeDelta: 0.1,
|
||||||
|
height: 300,
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface LocationItem {
|
||||||
|
id: string | number;
|
||||||
|
latitude: number;
|
||||||
|
longitude: number;
|
||||||
|
name: string;
|
||||||
|
imageId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default function Maps() {
|
export default function Maps() {
|
||||||
|
const [list, setList] = useState<any[] | null>(null);
|
||||||
|
const [loadList, setLoadList] = useState(false);
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
const [selected, setSelected] = useState({
|
||||||
|
id: "",
|
||||||
|
bidangBisnis: "",
|
||||||
|
nomorTelepon: "",
|
||||||
|
alamatBisnis: "",
|
||||||
|
namePin: "",
|
||||||
|
imageId: "",
|
||||||
|
portofolioId: "",
|
||||||
|
latitude: 0,
|
||||||
|
longitude: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
handlerLoadList();
|
||||||
|
}, [])
|
||||||
|
);
|
||||||
|
|
||||||
|
const handlerLoadList = async () => {
|
||||||
|
try {
|
||||||
|
setLoadList(true);
|
||||||
|
const response = await apiMapsGetAll();
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setList(response.data);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoadList(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewWrapper style={{ paddingInline: 0, paddingBlock: 0 }}>
|
<>
|
||||||
{/* <MapCustom height={"100%"} /> */}
|
<ViewWrapper style={{ paddingInline: 0, paddingBlock: 0 }}>
|
||||||
<View style={{ flex: 1 }}>
|
{/* <MapCustom height={"100%"} /> */}
|
||||||
<MapView
|
<View style={{ flex: 1 }}>
|
||||||
style={{
|
{loadList ? (
|
||||||
width: "100%",
|
<MapView
|
||||||
height: "100%",
|
initialRegion={defaultRegion}
|
||||||
}}
|
style={{
|
||||||
/>
|
width: "100%",
|
||||||
</View>
|
height: "100%",
|
||||||
</ViewWrapper>
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<MapView
|
||||||
|
initialRegion={defaultRegion}
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{list?.map((item: any, index: number) => {
|
||||||
|
return (
|
||||||
|
<Marker
|
||||||
|
key={item?.id}
|
||||||
|
coordinate={{
|
||||||
|
latitude: item?.latitude,
|
||||||
|
longitude: item?.longitude,
|
||||||
|
}}
|
||||||
|
title={item?.namePin}
|
||||||
|
onPress={() => {
|
||||||
|
setOpenDrawer(true);
|
||||||
|
setSelected({
|
||||||
|
id: item?.id,
|
||||||
|
bidangBisnis:
|
||||||
|
item?.Portofolio?.MasterBidangBisnis?.name,
|
||||||
|
nomorTelepon: item?.Portofolio?.tlpn,
|
||||||
|
alamatBisnis: item?.Portofolio?.alamatKantor,
|
||||||
|
namePin: item?.namePin,
|
||||||
|
imageId: item?.imageId,
|
||||||
|
portofolioId: item?.Portofolio?.id,
|
||||||
|
latitude: item?.latitude,
|
||||||
|
longitude: item?.longitude,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
// Gunakan gambar kustom jika tersedia
|
||||||
|
>
|
||||||
|
<View style={{}}>
|
||||||
|
<Image
|
||||||
|
source={{
|
||||||
|
uri: API_IMAGE.GET({
|
||||||
|
fileId: item?.Portofolio?.logoId,
|
||||||
|
}),
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
width: 30,
|
||||||
|
height: 30,
|
||||||
|
borderRadius: 100,
|
||||||
|
borderWidth: 1,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</Marker>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</MapView>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</ViewWrapper>
|
||||||
|
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<DummyLandscapeImage height={200} imageId={selected.imageId} />
|
||||||
|
<Spacing />
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<GridTwoView
|
||||||
|
spanLeft={2}
|
||||||
|
spanRight={10}
|
||||||
|
leftIcon={
|
||||||
|
<FontAwesome
|
||||||
|
name="building-o"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color="white"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
rightIcon={<TextCustom>{selected.namePin}</TextCustom>}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<GridTwoView
|
||||||
|
spanLeft={2}
|
||||||
|
spanRight={10}
|
||||||
|
leftIcon={
|
||||||
|
<Ionicons
|
||||||
|
name="list-outline"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color="white"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
rightIcon={<TextCustom>{selected.bidangBisnis}</TextCustom>}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<GridTwoView
|
||||||
|
spanLeft={2}
|
||||||
|
spanRight={10}
|
||||||
|
leftIcon={
|
||||||
|
<Ionicons
|
||||||
|
name="call-outline"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color="white"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
rightIcon={<TextCustom>{selected.nomorTelepon}</TextCustom>}
|
||||||
|
/>
|
||||||
|
<GridTwoView
|
||||||
|
spanLeft={2}
|
||||||
|
spanRight={10}
|
||||||
|
leftIcon={
|
||||||
|
<Ionicons
|
||||||
|
name="location-outline"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color="white"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
rightIcon={<TextCustom>{selected.alamatBisnis}</TextCustom>}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.Col span={6} style={{ paddingRight: 10 }}>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
setOpenDrawer(false);
|
||||||
|
router.push(`/portofolio/${selected.portofolioId}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</ButtonCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={6} style={{ paddingLeft: 10 }}>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
openInDeviceMaps({
|
||||||
|
latitude: selected.latitude,
|
||||||
|
longitude: selected.longitude,
|
||||||
|
title: selected.namePin,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Buka Maps
|
||||||
|
</ButtonCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</StackCustom>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import { DrawerCustom, LoaderCustom, Spacing, StackCustom } from "@/components";
|
import {
|
||||||
|
ButtonCustom,
|
||||||
|
DrawerCustom,
|
||||||
|
DummyLandscapeImage,
|
||||||
|
LoaderCustom,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
} from "@/components";
|
||||||
import LeftButtonCustom from "@/components/Button/BackButton";
|
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||||
|
import GridTwoView from "@/components/_ShareComponent/GridTwoView";
|
||||||
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import Portofolio_BusinessLocation from "@/screens/Portofolio/BusinessLocationSection";
|
import Portofolio_BusinessLocation from "@/screens/Portofolio/BusinessLocationSection";
|
||||||
import Portofolio_ButtonDelete from "@/screens/Portofolio/ButtonDelete";
|
import Portofolio_ButtonDelete from "@/screens/Portofolio/ButtonDelete";
|
||||||
@@ -13,19 +23,20 @@ import Portofolio_SocialMediaSection from "@/screens/Portofolio/SocialMediaSecti
|
|||||||
import { apiGetOnePortofolio } from "@/service/api-client/api-portofolio";
|
import { apiGetOnePortofolio } from "@/service/api-client/api-portofolio";
|
||||||
import { apiUser } from "@/service/api-client/api-user";
|
import { apiUser } from "@/service/api-client/api-user";
|
||||||
import { GStyles } from "@/styles/global-styles";
|
import { GStyles } from "@/styles/global-styles";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { openInDeviceMaps } from "@/utils/openInDeviceMaps";
|
||||||
|
import { FontAwesome, Ionicons } from "@expo/vector-icons";
|
||||||
import { Stack, useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { Stack, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
import { TouchableOpacity } from "react-native";
|
import { TouchableOpacity } from "react-native";
|
||||||
|
|
||||||
export default function Portofolio() {
|
export default function Portofolio() {
|
||||||
|
const { user } = useAuth();
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
||||||
const [isLoadingDelete, setIsLoadingDelete] = useState(false);
|
const [isLoadingDelete, setIsLoadingDelete] = useState(false);
|
||||||
const [data, setData] = useState<any>();
|
const [data, setData] = useState<any>();
|
||||||
const [profileId, setProfileId] = useState<any>();
|
const [profileId, setProfileId] = useState<any>();
|
||||||
|
const [openDrawerLocation, setOpenDrawerLocation] = useState(false);
|
||||||
const { user } = useAuth();
|
|
||||||
|
|
||||||
const openDrawer = () => {
|
const openDrawer = () => {
|
||||||
setIsDrawerOpen(true);
|
setIsDrawerOpen(true);
|
||||||
@@ -43,19 +54,13 @@ export default function Portofolio() {
|
|||||||
|
|
||||||
async function onLoadData(id: string) {
|
async function onLoadData(id: string) {
|
||||||
const response = await apiGetOnePortofolio({ id: id });
|
const response = await apiGetOnePortofolio({ id: id });
|
||||||
console.log(
|
|
||||||
"[PROFILE ID]>>",
|
|
||||||
JSON.stringify(response.data.Profile.id, null, 2)
|
|
||||||
);
|
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
const onLoadUserByToken = async () => {
|
const onLoadUserByToken = async () => {
|
||||||
const response = await apiUser(user?.id as string);
|
const response = await apiUser(user?.id as string);
|
||||||
console.log(
|
|
||||||
"[PROFILE LOGIN]>>",
|
|
||||||
JSON.stringify(response.data?.Profile.id, null, 2)
|
|
||||||
);
|
|
||||||
setProfileId(response?.data?.Profile?.id);
|
setProfileId(response?.data?.Profile?.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,7 +94,11 @@ export default function Portofolio() {
|
|||||||
data={data}
|
data={data}
|
||||||
listSubBidang={data?.Portofolio_BidangDanSubBidangBisnis as any[]}
|
listSubBidang={data?.Portofolio_BidangDanSubBidangBisnis as any[]}
|
||||||
/>
|
/>
|
||||||
<Portofolio_BusinessLocation />
|
<Portofolio_BusinessLocation
|
||||||
|
data={data?.BusinessMaps}
|
||||||
|
imageId={data?.logoId}
|
||||||
|
setOpenDrawerLocation={setOpenDrawerLocation}
|
||||||
|
/>
|
||||||
<Portofolio_SocialMediaSection
|
<Portofolio_SocialMediaSection
|
||||||
data={data?.Portofolio_MediaSosial}
|
data={data?.Portofolio_MediaSosial}
|
||||||
/>
|
/>
|
||||||
@@ -110,10 +119,93 @@ export default function Portofolio() {
|
|||||||
height={"auto"}
|
height={"auto"}
|
||||||
>
|
>
|
||||||
<Portofolio_MenuDrawerSection
|
<Portofolio_MenuDrawerSection
|
||||||
drawerItems={drawerItemsPortofolio({ id: id as string })}
|
drawerItems={drawerItemsPortofolio({
|
||||||
|
id: id as string,
|
||||||
|
maps: data?.BusinessMaps,
|
||||||
|
})}
|
||||||
setIsDrawerOpen={setIsDrawerOpen}
|
setIsDrawerOpen={setIsDrawerOpen}
|
||||||
/>
|
/>
|
||||||
</DrawerCustom>
|
</DrawerCustom>
|
||||||
|
|
||||||
|
{/* Drawer Lokasi */}
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawerLocation}
|
||||||
|
closeDrawer={() => setOpenDrawerLocation(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<DummyLandscapeImage
|
||||||
|
height={200}
|
||||||
|
imageId={data?.BusinessMaps?.imageId}
|
||||||
|
/>
|
||||||
|
<Spacing />
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<GridTwoView
|
||||||
|
spanLeft={2}
|
||||||
|
spanRight={10}
|
||||||
|
leftIcon={
|
||||||
|
<FontAwesome
|
||||||
|
name="building-o"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color="white"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
rightIcon={<TextCustom>{data?.BusinessMaps?.namePin}</TextCustom>}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<GridTwoView
|
||||||
|
spanLeft={2}
|
||||||
|
spanRight={10}
|
||||||
|
leftIcon={
|
||||||
|
<Ionicons
|
||||||
|
name="list-outline"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color="white"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
rightIcon={
|
||||||
|
<TextCustom>{data?.MasterBidangBisnis?.name}</TextCustom>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<GridTwoView
|
||||||
|
spanLeft={2}
|
||||||
|
spanRight={10}
|
||||||
|
leftIcon={
|
||||||
|
<Ionicons
|
||||||
|
name="call-outline"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color="white"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
rightIcon={<TextCustom>{data?.tlpn}</TextCustom>}
|
||||||
|
/>
|
||||||
|
<GridTwoView
|
||||||
|
spanLeft={2}
|
||||||
|
spanRight={10}
|
||||||
|
leftIcon={
|
||||||
|
<Ionicons
|
||||||
|
name="location-outline"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color="white"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
rightIcon={<TextCustom>{data?.alamatKantor}</TextCustom>}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Spacing />
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
openInDeviceMaps({
|
||||||
|
latitude: data?.BusinessMaps?.latitude,
|
||||||
|
longitude: data?.BusinessMaps?.longitude,
|
||||||
|
title: data?.BusinessMaps?.namePin,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Buka Maps
|
||||||
|
</ButtonCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</DrawerCustom>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// components/MapComponent.js
|
// components/MapComponent.js
|
||||||
|
|
||||||
|
import API_IMAGE from "@/constants/api-storage";
|
||||||
|
import { Image } from "expo-image";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { DimensionValue, StyleSheet, View } from "react-native";
|
import { DimensionValue, StyleSheet, View } from "react-native";
|
||||||
import MapView, { Marker } from "react-native-maps";
|
import MapView, { Marker } from "react-native-maps";
|
||||||
@@ -10,6 +12,9 @@ interface MapComponentProps {
|
|||||||
latitudeDelta?: number;
|
latitudeDelta?: number;
|
||||||
longitudeDelta?: number;
|
longitudeDelta?: number;
|
||||||
height?: DimensionValue;
|
height?: DimensionValue;
|
||||||
|
namePin?: string;
|
||||||
|
imageId?: string;
|
||||||
|
onPress?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MapCustom = ({
|
const MapCustom = ({
|
||||||
@@ -18,6 +23,9 @@ const MapCustom = ({
|
|||||||
latitudeDelta = 0.1,
|
latitudeDelta = 0.1,
|
||||||
longitudeDelta = 0.1,
|
longitudeDelta = 0.1,
|
||||||
height = 300,
|
height = 300,
|
||||||
|
namePin = "Bali",
|
||||||
|
imageId,
|
||||||
|
onPress,
|
||||||
}: MapComponentProps) => {
|
}: MapComponentProps) => {
|
||||||
const initialRegion = {
|
const initialRegion = {
|
||||||
latitude,
|
latitude,
|
||||||
@@ -40,9 +48,22 @@ const MapCustom = ({
|
|||||||
latitude,
|
latitude,
|
||||||
longitude,
|
longitude,
|
||||||
}}
|
}}
|
||||||
title="Bali"
|
title={namePin}
|
||||||
description="Badung, Bali, Indonesia"
|
onPress={onPress}
|
||||||
/>
|
// Gunakan gambar kustom jika tersedia
|
||||||
|
>
|
||||||
|
<View style={{}}>
|
||||||
|
<Image
|
||||||
|
source={{ uri: API_IMAGE.GET({ fileId: imageId as string }) }}
|
||||||
|
style={{
|
||||||
|
width: 30,
|
||||||
|
height: 30,
|
||||||
|
borderRadius: 100,
|
||||||
|
borderWidth: 1,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</Marker>
|
||||||
</MapView>
|
</MapView>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|||||||
79
components/Map/MapSelected.tsx
Normal file
79
components/Map/MapSelected.tsx
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { StyleSheet, View } from "react-native";
|
||||||
|
import MapView, { LatLng, Marker } from "react-native-maps";
|
||||||
|
|
||||||
|
interface MapSelectedProps {
|
||||||
|
initialRegion?: {
|
||||||
|
latitude?: number;
|
||||||
|
longitude?: number;
|
||||||
|
latitudeDelta?: number;
|
||||||
|
longitudeDelta?: number;
|
||||||
|
};
|
||||||
|
onLocationSelect?: (location: LatLng) => void;
|
||||||
|
height?: number; // Opsional: tinggi peta dalam piksel
|
||||||
|
selectedLocation: LatLng;
|
||||||
|
setSelectedLocation: (location: LatLng) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MapSelected: React.FC<MapSelectedProps> = ({
|
||||||
|
initialRegion,
|
||||||
|
onLocationSelect,
|
||||||
|
selectedLocation,
|
||||||
|
setSelectedLocation,
|
||||||
|
height = 400, // Default height: 400
|
||||||
|
}) => {
|
||||||
|
const handleMapPress = (event: any) => {
|
||||||
|
const { latitude, longitude } = event.nativeEvent.coordinate;
|
||||||
|
const location = { latitude, longitude };
|
||||||
|
setSelectedLocation(location);
|
||||||
|
onLocationSelect?.(location);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Default region sesuai permintaan
|
||||||
|
const defaultRegion = {
|
||||||
|
latitude: -8.737109,
|
||||||
|
longitude: 115.1756897,
|
||||||
|
latitudeDelta: 0.1,
|
||||||
|
longitudeDelta: 0.1,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={[styles.container, { height }]}>
|
||||||
|
<MapView
|
||||||
|
style={styles.map}
|
||||||
|
initialRegion={(initialRegion as any) || defaultRegion}
|
||||||
|
onPress={handleMapPress}
|
||||||
|
showsUserLocation={true}
|
||||||
|
showsMyLocationButton={true}
|
||||||
|
loadingEnabled={true}
|
||||||
|
loadingIndicatorColor="#666"
|
||||||
|
loadingBackgroundColor="#f0f0f0"
|
||||||
|
>
|
||||||
|
{selectedLocation && (
|
||||||
|
<Marker
|
||||||
|
coordinate={selectedLocation}
|
||||||
|
title="Lokasi Dipilih"
|
||||||
|
description={`Lat: ${selectedLocation.latitude.toFixed(
|
||||||
|
6
|
||||||
|
)}, Lng: ${selectedLocation.longitude.toFixed(6)}`}
|
||||||
|
pinColor="red"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</MapView>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
width: "100%",
|
||||||
|
backgroundColor: "#f5f5f5",
|
||||||
|
overflow: "hidden",
|
||||||
|
borderRadius: 8,
|
||||||
|
},
|
||||||
|
map: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default MapSelected;
|
||||||
29
components/_ShareComponent/GridTwoView.tsx
Normal file
29
components/_ShareComponent/GridTwoView.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { StyleProp, ViewStyle } from "react-native";
|
||||||
|
import Grid from "../Grid/GridCustom";
|
||||||
|
|
||||||
|
export default function GridTwoView({
|
||||||
|
spanLeft = 6,
|
||||||
|
spanRight = 6,
|
||||||
|
leftIcon,
|
||||||
|
rightIcon,
|
||||||
|
styleLeft,
|
||||||
|
styleRight,
|
||||||
|
}: {
|
||||||
|
spanLeft?: number;
|
||||||
|
spanRight?: number;
|
||||||
|
leftIcon?: React.ReactNode;
|
||||||
|
rightIcon?: React.ReactNode;
|
||||||
|
styleLeft?: StyleProp<ViewStyle>;
|
||||||
|
styleRight?: StyleProp<ViewStyle>;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Grid containerStyle={{ marginBottom: 0 }}>
|
||||||
|
<Grid.Col span={spanLeft} style={{ justifyContent: "center" }}>
|
||||||
|
{leftIcon}
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={spanRight} style={{ justifyContent: "center" }}>
|
||||||
|
{rightIcon}
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,12 +1,45 @@
|
|||||||
import { BaseBox, MapCustom, StackCustom, TextCustom } from "@/components";
|
import {
|
||||||
|
BaseBox,
|
||||||
|
MapCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom
|
||||||
|
} from "@/components";
|
||||||
|
|
||||||
export default function Portofolio_BusinessLocation() {
|
export default function Portofolio_BusinessLocation({
|
||||||
|
data,
|
||||||
|
imageId,
|
||||||
|
setOpenDrawerLocation,
|
||||||
|
}: {
|
||||||
|
data: any;
|
||||||
|
imageId?: string;
|
||||||
|
setOpenDrawerLocation: (value: boolean) => void;
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<BaseBox>
|
<BaseBox style={{ height: !data ? 200 : "auto" }}>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<TextCustom bold>Lokasi Bisnis</TextCustom>
|
<TextCustom bold>Lokasi Bisnis</TextCustom>
|
||||||
<MapCustom />
|
{!data ? (
|
||||||
|
<TextCustom
|
||||||
|
style={{ paddingTop: 50 }}
|
||||||
|
align="center"
|
||||||
|
color="gray"
|
||||||
|
size={"small"}
|
||||||
|
bold
|
||||||
|
>
|
||||||
|
Lokasi bisnis belum ditambahkan
|
||||||
|
</TextCustom>
|
||||||
|
) : (
|
||||||
|
<MapCustom
|
||||||
|
latitude={data?.latitude}
|
||||||
|
longitude={data?.longitude}
|
||||||
|
namePin={data?.namePin}
|
||||||
|
imageId={imageId}
|
||||||
|
onPress={() => {
|
||||||
|
setOpenDrawerLocation(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -41,7 +41,11 @@ export default function Portofolio_Data({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: (
|
icon: (
|
||||||
<Ionicons name="home-outline" size={ICON_SIZE_SMALL} color="white" />
|
<Ionicons
|
||||||
|
name="location-outline"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color="white"
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
label: data && data?.alamatKantor ? data.alamatKantor : "-",
|
label: data && data?.alamatKantor ? data.alamatKantor : "-",
|
||||||
},
|
},
|
||||||
@@ -89,8 +93,6 @@ export default function Portofolio_Data({
|
|||||||
// },
|
// },
|
||||||
// ];
|
// ];
|
||||||
|
|
||||||
// console.log("List Sub Bidang >>", JSON.stringify(listSubBidang, null, 2));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<BaseBox>
|
<BaseBox>
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
import { AccentColor } from "@/constants/color-palet";
|
import { AccentColor } from "@/constants/color-palet";
|
||||||
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
|
||||||
import { Ionicons, FontAwesome5, FontAwesome, Fontisto } from "@expo/vector-icons";
|
import {
|
||||||
|
FontAwesome,
|
||||||
|
Fontisto,
|
||||||
|
Ionicons
|
||||||
|
} from "@expo/vector-icons";
|
||||||
|
|
||||||
export const drawerItemsPortofolio = ({ id }: { id: string }): IMenuDrawerItem[] => [
|
export const drawerItemsPortofolio = ({
|
||||||
|
id,
|
||||||
|
maps,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
maps: any;
|
||||||
|
}): IMenuDrawerItem[] => [
|
||||||
{
|
{
|
||||||
icon: (
|
icon: (
|
||||||
<Ionicons
|
<Ionicons
|
||||||
@@ -45,18 +55,20 @@ export const drawerItemsPortofolio = ({ id }: { id: string }): IMenuDrawerItem[]
|
|||||||
color={AccentColor.white}
|
color={AccentColor.white}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
label: "Edit Map",
|
label: `${!maps ? "Tambah" : "Edit"} Map`,
|
||||||
path: `/(application)/maps/${id}/edit`,
|
path: !maps
|
||||||
},
|
? `/(application)/maps/create?id=${id}`
|
||||||
{
|
: `/(application)/maps/${maps?.id}/edit`,
|
||||||
icon: (
|
|
||||||
<FontAwesome5
|
|
||||||
name="map-pin"
|
|
||||||
size={ICON_SIZE_MEDIUM}
|
|
||||||
color={AccentColor.white}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
label: "Custom Pin Map",
|
|
||||||
path: `/(application)/maps/${id}/custom-pin`,
|
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// icon: (
|
||||||
|
// <FontAwesome5
|
||||||
|
// name="map-pin"
|
||||||
|
// size={ICON_SIZE_MEDIUM}
|
||||||
|
// color={AccentColor.white}
|
||||||
|
// />
|
||||||
|
// ),
|
||||||
|
// label: "Custom Pin Map",
|
||||||
|
// path: `/(application)/maps/${id}/custom-pin`,
|
||||||
|
// },
|
||||||
];
|
];
|
||||||
|
|||||||
41
service/api-client/api-maps.ts
Normal file
41
service/api-client/api-maps.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { apiConfig } from "../api-config";
|
||||||
|
|
||||||
|
export async function apiMapsCreate({ data }: { data: any }) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.post(`/mobile/maps`, {
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiMapsGetAll() {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.get("/mobile/maps");
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiMapsGetOne({ id }: { id: string }) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.get(`/mobile/maps/${id}`);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiMapsUpdate({ id, data }: { id: string; data: any }) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.put(`/mobile/maps/${id}`, {
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
37
utils/openInDeviceMaps.ts
Normal file
37
utils/openInDeviceMaps.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { Platform, Linking, Alert } from "react-native";
|
||||||
|
|
||||||
|
export const openInDeviceMaps = async ({
|
||||||
|
latitude,
|
||||||
|
longitude,
|
||||||
|
title = "Lokasi",
|
||||||
|
}: {
|
||||||
|
latitude: number;
|
||||||
|
longitude: number;
|
||||||
|
title?: string;
|
||||||
|
}) => {
|
||||||
|
let url = "";
|
||||||
|
|
||||||
|
if (Platform.OS === "ios") {
|
||||||
|
// Apple Maps
|
||||||
|
url = `maps://?q=${encodeURIComponent(title)}&ll=${latitude},${longitude}`;
|
||||||
|
} else {
|
||||||
|
// Android: Google Maps
|
||||||
|
url = `geo:${latitude},${longitude}?q=${latitude},${longitude}(${encodeURIComponent(
|
||||||
|
title
|
||||||
|
)})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const canOpen = await Linking.canOpenURL(url);
|
||||||
|
if (canOpen) {
|
||||||
|
await Linking.openURL(url);
|
||||||
|
} else {
|
||||||
|
// Fallback ke web
|
||||||
|
const webUrl = `https://www.google.com/maps/search/?api=1&query=${latitude},${longitude}`;
|
||||||
|
await Linking.openURL(webUrl);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Gagal membuka Maps:", error);
|
||||||
|
Alert.alert("Error", "Tidak dapat membuka aplikasi Maps.");
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user