Compare commits
7 Commits
qc/9-dec-2
...
notificati
| Author | SHA1 | Date | |
|---|---|---|---|
| 05c1cac10f | |||
| d27c01ed56 | |||
| 34680a4c38 | |||
| 43c8c105cf | |||
| 2c0198b1b7 | |||
| 573b525352 | |||
| 6f9481c7c9 |
@@ -15,7 +15,11 @@
|
|||||||
<data android:scheme="https"/>
|
<data android:scheme="https"/>
|
||||||
</intent>
|
</intent>
|
||||||
</queries>
|
</queries>
|
||||||
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:supportsRtl="true" android:enableOnBackInvokedCallback="false">
|
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:supportsRtl="true" android:enableOnBackInvokedCallback="false" android:fullBackupContent="@xml/secure_store_backup_rules" android:dataExtractionRules="@xml/secure_store_data_extraction_rules">
|
||||||
|
<meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/notification_icon_color"/>
|
||||||
|
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon"/>
|
||||||
|
<meta-data android:name="expo.modules.notifications.default_notification_color" android:resource="@color/notification_icon_color"/>
|
||||||
|
<meta-data android:name="expo.modules.notifications.default_notification_icon" android:resource="@drawable/notification_icon"/>
|
||||||
<meta-data android:name="expo.modules.updates.ENABLED" android:value="false"/>
|
<meta-data android:name="expo.modules.updates.ENABLED" android:value="false"/>
|
||||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
|
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
|
||||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
|
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
|
||||||
|
|||||||
BIN
android/app/src/main/res/drawable-hdpi/notification_icon.png
Normal file
BIN
android/app/src/main/res/drawable-hdpi/notification_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
BIN
android/app/src/main/res/drawable-mdpi/notification_icon.png
Normal file
BIN
android/app/src/main/res/drawable-mdpi/notification_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
android/app/src/main/res/drawable-xhdpi/notification_icon.png
Normal file
BIN
android/app/src/main/res/drawable-xhdpi/notification_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
BIN
android/app/src/main/res/drawable-xxhdpi/notification_icon.png
Normal file
BIN
android/app/src/main/res/drawable-xxhdpi/notification_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
BIN
android/app/src/main/res/drawable-xxxhdpi/notification_icon.png
Normal file
BIN
android/app/src/main/res/drawable-xxxhdpi/notification_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.6 KiB |
@@ -3,4 +3,5 @@
|
|||||||
<color name="iconBackground">#ffffff</color>
|
<color name="iconBackground">#ffffff</color>
|
||||||
<color name="colorPrimary">#023c69</color>
|
<color name="colorPrimary">#023c69</color>
|
||||||
<color name="colorPrimaryDark">#ffffff</color>
|
<color name="colorPrimaryDark">#ffffff</color>
|
||||||
|
<color name="notification_icon_color">#ffffff</color>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -14,12 +14,14 @@ export default {
|
|||||||
ios: {
|
ios: {
|
||||||
supportsTablet: true,
|
supportsTablet: true,
|
||||||
bundleIdentifier: "com.anonymous.hipmi-mobile",
|
bundleIdentifier: "com.anonymous.hipmi-mobile",
|
||||||
|
googleServicesFile: "./ios/HIPMIBadungConnect/GoogleService-Info.plist",
|
||||||
infoPlist: {
|
infoPlist: {
|
||||||
ITSAppUsesNonExemptEncryption: false,
|
ITSAppUsesNonExemptEncryption: false,
|
||||||
"NSLocationWhenInUseUsageDescription": "Aplikasi membutuhkan akses lokasi untuk menampilkan peta.",
|
NSLocationWhenInUseUsageDescription:
|
||||||
|
"Aplikasi membutuhkan akses lokasi untuk menampilkan peta.",
|
||||||
},
|
},
|
||||||
associatedDomains: ["applinks:cld-dkr-staging-hipmi.wibudev.com"],
|
associatedDomains: ["applinks:cld-dkr-staging-hipmi.wibudev.com"],
|
||||||
buildNumber: "13",
|
buildNumber: "15",
|
||||||
},
|
},
|
||||||
|
|
||||||
android: {
|
android: {
|
||||||
@@ -56,7 +58,6 @@ export default {
|
|||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
"expo-router",
|
"expo-router",
|
||||||
"expo-notifications",
|
|
||||||
"expo-web-browser",
|
"expo-web-browser",
|
||||||
[
|
[
|
||||||
"expo-splash-screen",
|
"expo-splash-screen",
|
||||||
@@ -77,6 +78,15 @@ export default {
|
|||||||
],
|
],
|
||||||
"expo-font",
|
"expo-font",
|
||||||
"@rnmapbox/maps",
|
"@rnmapbox/maps",
|
||||||
|
"@react-native-firebase/app",
|
||||||
|
[
|
||||||
|
"expo-notifications",
|
||||||
|
{
|
||||||
|
icon: "./assets/images/icon.png",
|
||||||
|
color: "#ffffff",
|
||||||
|
iosDisplayInForeground: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
experiments: {
|
experiments: {
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import { StackCustom, ViewWrapper } from "@/components";
|
import { ButtonCustom, StackCustom, ViewWrapper } from "@/components";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
import { useNotificationStore } from "@/hooks/use-notification-store";
|
||||||
import Home_BottomFeatureSection from "@/screens/Home/bottomFeatureSection";
|
import Home_BottomFeatureSection from "@/screens/Home/bottomFeatureSection";
|
||||||
|
import HeaderBell from "@/screens/Home/HeaderBell";
|
||||||
import Home_ImageSection from "@/screens/Home/imageSection";
|
import Home_ImageSection from "@/screens/Home/imageSection";
|
||||||
import TabSection from "@/screens/Home/tabSection";
|
import TabSection from "@/screens/Home/tabSection";
|
||||||
import { tabsHome } from "@/screens/Home/tabsList";
|
import { tabsHome } from "@/screens/Home/tabsList";
|
||||||
@@ -13,15 +15,19 @@ import { apiVersion } from "@/service/api-config";
|
|||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import { Redirect, router, Stack, useFocusEffect } from "expo-router";
|
import { Redirect, router, Stack, useFocusEffect } from "expo-router";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { RefreshControl } from "react-native";
|
import { RefreshControl, Text, View } from "react-native";
|
||||||
|
|
||||||
export default function Application() {
|
export default function Application() {
|
||||||
const { token, user, userData } = useAuth();
|
const { token, user, userData } = useAuth();
|
||||||
const [data, setData] = useState<any>();
|
const [data, setData] = useState<any>();
|
||||||
const [refreshing, setRefreshing] = useState(false);
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
console.log("[User] >>", JSON.stringify(user?.id, null, 2))
|
// console.log("[User] >>", JSON.stringify(user?.id, null, 2));
|
||||||
|
|
||||||
|
// const { notifications } = useNotificationStore();
|
||||||
|
// const unreadCount = notifications.filter((n) => !n.read).length;
|
||||||
|
// console.log("UNREAD", notifications)
|
||||||
// ‼️ Untuk cek apakah: 1. user ada, 2. user punya profile, 3. accept temrs of forum nya ada atau tidak
|
// ‼️ Untuk cek apakah: 1. user ada, 2. user punya profile, 3. accept temrs of forum nya ada atau tidak
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
onLoadData();
|
onLoadData();
|
||||||
@@ -32,7 +38,10 @@ export default function Application() {
|
|||||||
|
|
||||||
async function onLoadData() {
|
async function onLoadData() {
|
||||||
const response = await apiUser(user?.id as string);
|
const response = await apiUser(user?.id as string);
|
||||||
console.log("[Profile ID]>>", JSON.stringify(response?.data?.Profile?.id, null, 2));
|
console.log(
|
||||||
|
"[Profile ID]>>",
|
||||||
|
JSON.stringify(response?.data?.Profile?.id, null, 2)
|
||||||
|
);
|
||||||
|
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
}
|
}
|
||||||
@@ -79,16 +88,47 @@ export default function Application() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
headerRight: () => (
|
headerRight: () => <HeaderBell />,
|
||||||
<Ionicons
|
// headerRight: () => {
|
||||||
name="notifications"
|
// return (
|
||||||
size={20}
|
// <View style={{ position: "relative" }}>
|
||||||
color={MainColor.yellow}
|
// <Ionicons
|
||||||
onPress={() => {
|
// name="notifications"
|
||||||
router.push("/notifications");
|
// size={20}
|
||||||
}}
|
// color={MainColor.yellow}
|
||||||
/>
|
// onPress={() => {
|
||||||
),
|
// router.push("/notifications");
|
||||||
|
// }}
|
||||||
|
// />
|
||||||
|
// {unreadCount > 0 && (
|
||||||
|
// <View
|
||||||
|
// style={{
|
||||||
|
// position: "absolute",
|
||||||
|
// top: -4,
|
||||||
|
// right: -4,
|
||||||
|
// backgroundColor: "red",
|
||||||
|
// borderRadius: 8,
|
||||||
|
// minWidth: 16,
|
||||||
|
// height: 16,
|
||||||
|
// justifyContent: "center",
|
||||||
|
// alignItems: "center",
|
||||||
|
// paddingHorizontal: 2,
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// <Text
|
||||||
|
// style={{
|
||||||
|
// color: "white",
|
||||||
|
// fontSize: 10,
|
||||||
|
// fontWeight: "bold",
|
||||||
|
// }}
|
||||||
|
// >
|
||||||
|
// {unreadCount > 9 ? "9+" : unreadCount}
|
||||||
|
// </Text>
|
||||||
|
// </View>
|
||||||
|
// )}
|
||||||
|
// </View>
|
||||||
|
// );
|
||||||
|
// },
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ViewWrapper
|
<ViewWrapper
|
||||||
@@ -105,6 +145,8 @@ export default function Application() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
|
{/* <ButtonCustom onPress={() => router.push("./test-notifications")}>Test Notif</ButtonCustom> */}
|
||||||
|
|
||||||
<Home_ImageSection />
|
<Home_ImageSection />
|
||||||
|
|
||||||
<Home_FeatureSection />
|
<Home_FeatureSection />
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ import {
|
|||||||
import pickImage from "@/utils/pickImage";
|
import pickImage from "@/utils/pickImage";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import { Image } from "expo-image";
|
import { Image } from "expo-image";
|
||||||
import { useLocalSearchParams } from "expo-router";
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { Text, TouchableOpacity, View } from "react-native";
|
import { Text, TouchableOpacity, View } from "react-native";
|
||||||
import PhoneInput, { ICountry } from "react-native-international-phone-number";
|
import PhoneInput, { ICountry } from "react-native-international-phone-number";
|
||||||
import { Avatar } from "react-native-paper";
|
import { Avatar } from "react-native-paper";
|
||||||
@@ -85,10 +85,12 @@ export default function PortofolioCreate() {
|
|||||||
setSelectedCountry(country);
|
setSelectedCountry(country);
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useFocusEffect(
|
||||||
onLoadMaster();
|
useCallback(() => {
|
||||||
onLoadMasterSubBidangBisnis();
|
onLoadMaster();
|
||||||
}, []);
|
onLoadMasterSubBidangBisnis();
|
||||||
|
}, [])
|
||||||
|
);
|
||||||
|
|
||||||
const onLoadMaster = async () => {
|
const onLoadMaster = async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
48
app/(application)/(user)/test-notifications.tsx
Normal file
48
app/(application)/(user)/test-notifications.tsx
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import {
|
||||||
|
ButtonCustom,
|
||||||
|
NewWrapper,
|
||||||
|
StackCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
} from "@/components";
|
||||||
|
import { apiNotificationsSend } from "@/service/api-notifications";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function TestNotification() {
|
||||||
|
const [data, setData] = useState("");
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
console.log("[Data Dikirim]", data);
|
||||||
|
const response = await apiNotificationsSend({
|
||||||
|
data: {
|
||||||
|
fcmToken:
|
||||||
|
"cVmHm-3P4E-1vjt6AA9kSF:APA91bHTkHjGTLxrFsb6Le6bZmzboZhwMGYXU4p0FP9yEeXixLDXNKS4F5vLuZV3sRgSnjjQsPpLOgstVLHJB8VJTObctKLdN-CxAp4dnP7Jbc_mH53jWvs",
|
||||||
|
title: "Test dari Backend (App Router)!",
|
||||||
|
body: data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[RES SEND NOTIF]", JSON.stringify(response.data, null, 2));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<NewWrapper>
|
||||||
|
<StackCustom>
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
label="Nama"
|
||||||
|
placeholder="Masukkan nama"
|
||||||
|
value={data}
|
||||||
|
onChangeText={(text) => setData(text)}
|
||||||
|
/>
|
||||||
|
<ButtonCustom
|
||||||
|
onPress={() => {
|
||||||
|
handleSubmit();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Kirim
|
||||||
|
</ButtonCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</NewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -110,7 +110,7 @@ export default function VotingCreate() {
|
|||||||
<StackCustom gap={"xs"}>
|
<StackCustom gap={"xs"}>
|
||||||
<TextInputCustom
|
<TextInputCustom
|
||||||
label="Judul Voting"
|
label="Judul Voting"
|
||||||
placeholder="MasukanJudul Voting"
|
placeholder="Masukan Judul Voting"
|
||||||
required
|
required
|
||||||
value={data.title}
|
value={data.title}
|
||||||
onChangeText={(value: any) => setData({ ...data, title: value })}
|
onChangeText={(value: any) => setData({ ...data, title: value })}
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
import {
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import {
|
||||||
|
apiAdminMasterBusinessFieldById,
|
||||||
|
apiAdminMasterBusinessFieldUpdate,
|
||||||
|
} from "@/service/api-admin/api-master-admin";
|
||||||
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
import { Switch } from "react-native-paper";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
|
export default function AdminAppInformation_BusinessFieldDetail() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [data, setData] = useState<any | null>(null);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadDetail();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadDetail = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiAdminMasterBusinessFieldById({
|
||||||
|
id: id as string,
|
||||||
|
category: "bidang"
|
||||||
|
});
|
||||||
|
|
||||||
|
setData(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
setData(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlerSubmit = async () => {
|
||||||
|
if (!data.name) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Lengkapi Data",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const response = await apiAdminMasterBusinessFieldUpdate({
|
||||||
|
id: id as string,
|
||||||
|
data: data,
|
||||||
|
category: "bidang",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal update data",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Data berhasil di update",
|
||||||
|
});
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const buttonSubmit = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
disabled={!data?.name}
|
||||||
|
isLoading={isLoading}
|
||||||
|
onPress={() => handlerSubmit()}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper footerComponent={buttonSubmit}>
|
||||||
|
<StackCustom>
|
||||||
|
<AdminBackButtonAntTitle title="Update Bidang Bisnis" />
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
label="Nama Bidang Bisnis"
|
||||||
|
placeholder="Masukan Nama Bidang Bisnis"
|
||||||
|
required
|
||||||
|
value={data?.name}
|
||||||
|
onChangeText={(value) => setData({ ...data, name: value })}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<StackCustom
|
||||||
|
gap={"sm"}
|
||||||
|
style={{
|
||||||
|
alignContent: "flex-start",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextCustom>Status</TextCustom>
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
style={{
|
||||||
|
alignSelf: "flex-start",
|
||||||
|
}}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
value={data?.active}
|
||||||
|
onValueChange={(value) => setData({ ...data, active: value })}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BoxButtonOnFooter,
|
ActionIcon,
|
||||||
ButtonCustom,
|
BaseBox,
|
||||||
|
CenterCustom,
|
||||||
|
LoaderCustom,
|
||||||
|
Spacing,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
TextInputCustom,
|
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
|
import { IconEdit } from "@/components/_Icon";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
|
import { GridSpan_NewComponent } from "@/components/_ShareComponent/GridSpan_NewComponent";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
import {
|
import { apiAdminMasterBusinessFieldById } from "@/service/api-admin/api-master-admin";
|
||||||
apiAdminMasterBusinessFieldById,
|
|
||||||
apiAdminMasterBusinessFieldUpdate,
|
|
||||||
} from "@/service/api-admin/api-master-admin";
|
|
||||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
import { Switch } from "react-native-paper";
|
import { Divider } from "react-native-paper";
|
||||||
import Toast from "react-native-toast-message";
|
|
||||||
|
|
||||||
export default function AdminAppInformation_BusinessFieldDetail() {
|
export default function AdminAppInformation_BusinessFieldDetail() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
@@ -33,8 +33,11 @@ export default function AdminAppInformation_BusinessFieldDetail() {
|
|||||||
try {
|
try {
|
||||||
const response = await apiAdminMasterBusinessFieldById({
|
const response = await apiAdminMasterBusinessFieldById({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
|
category: "all",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log("Response >>", JSON.stringify(response, null, 2));
|
||||||
|
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
@@ -42,73 +45,89 @@ export default function AdminAppInformation_BusinessFieldDetail() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlerSubmit = async () => {
|
|
||||||
if (!data.name) {
|
|
||||||
Toast.show({
|
|
||||||
type: "error",
|
|
||||||
text1: "Lengkapi Data",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
setIsLoading(true);
|
|
||||||
const response = await apiAdminMasterBusinessFieldUpdate({
|
|
||||||
id: id as string,
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.success) {
|
|
||||||
Toast.show({
|
|
||||||
type: "error",
|
|
||||||
text1: "Gagal update data",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toast.show({
|
|
||||||
type: "success",
|
|
||||||
text1: "Data berhasil di update",
|
|
||||||
});
|
|
||||||
router.back();
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const buttonSubmit = (
|
|
||||||
<BoxButtonOnFooter>
|
|
||||||
<ButtonCustom
|
|
||||||
disabled={!data?.name}
|
|
||||||
isLoading={isLoading}
|
|
||||||
onPress={() => handlerSubmit()}
|
|
||||||
>
|
|
||||||
Update
|
|
||||||
</ButtonCustom>
|
|
||||||
</BoxButtonOnFooter>
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper footerComponent={buttonSubmit}>
|
<ViewWrapper>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<AdminBackButtonAntTitle title="Update Bidang Bisnis" />
|
<AdminBackButtonAntTitle title="Detail Bidang & Sub Bidang" />
|
||||||
|
|
||||||
<TextInputCustom
|
{!data ? (
|
||||||
label="Nama Bidang Bisnis"
|
<LoaderCustom />
|
||||||
placeholder="Masukan Nama Bidang Bisnis"
|
) : (
|
||||||
required
|
<StackCustom gap={"xs"}>
|
||||||
value={data?.name}
|
<TextCustom bold>Nama Bidang</TextCustom>
|
||||||
onChangeText={(value) => setData({ ...data, name: value })}
|
<Spacing height={5} />
|
||||||
/>
|
<BaseBox>
|
||||||
|
<StackCustom gap={"xs"}>
|
||||||
|
<TextCustom bold>
|
||||||
|
Status: {data?.bidang?.active ? "Aktif" : "Tidak Aktif"}
|
||||||
|
</TextCustom>
|
||||||
|
<GridSpan_NewComponent
|
||||||
|
span1={10}
|
||||||
|
span2={2}
|
||||||
|
text1={
|
||||||
|
<TextCustom bold size={"large"}>
|
||||||
|
{data?.bidang?.name}
|
||||||
|
</TextCustom>
|
||||||
|
}
|
||||||
|
text2={
|
||||||
|
<CenterCustom>
|
||||||
|
<ActionIcon
|
||||||
|
icon={<IconEdit size={16} color={MainColor.black} />}
|
||||||
|
onPress={() =>
|
||||||
|
router.push(
|
||||||
|
`/admin/app-information/business-field/${id}/bidang-update`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</CenterCustom>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
{/* <Divider /> */}
|
||||||
|
<Spacing height={5} />
|
||||||
|
|
||||||
<TextCustom>Status Aktivasi</TextCustom>
|
<TextCustom bold>Sub Bidang Bisnis</TextCustom>
|
||||||
<Switch
|
<Spacing height={5} />
|
||||||
color={MainColor.yellow}
|
|
||||||
value={data?.active}
|
{data?.subBidang?.map((item: any, index: number) => (
|
||||||
onValueChange={(value) => setData({ ...data, active: value })}
|
<BaseBox key={index}>
|
||||||
/>
|
<StackCustom gap={0}>
|
||||||
|
<TextCustom bold>
|
||||||
|
Status: {item?.isActive ? "Aktif" : "Tidak Aktif"}
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<GridSpan_NewComponent
|
||||||
|
span1={10}
|
||||||
|
span2={2}
|
||||||
|
text1={
|
||||||
|
<TextCustom bold size={"large"}>
|
||||||
|
{item.name}
|
||||||
|
</TextCustom>
|
||||||
|
}
|
||||||
|
text2={
|
||||||
|
<CenterCustom>
|
||||||
|
<ActionIcon
|
||||||
|
icon={
|
||||||
|
<IconEdit size={16} color={MainColor.black} />
|
||||||
|
}
|
||||||
|
onPress={() =>
|
||||||
|
router.push(
|
||||||
|
`/admin/app-information/business-field/${item?.id}/sub-bidang-update`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</CenterCustom>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
))}
|
||||||
|
</StackCustom>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* <TextCustom>{JSON.stringify(data, null, 2)}</TextCustom> */}
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
import {
|
||||||
|
BoxButtonOnFooter,
|
||||||
|
ButtonCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
|
} from "@/components";
|
||||||
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import {
|
||||||
|
apiAdminMasterBusinessFieldById,
|
||||||
|
apiAdminMasterBusinessFieldUpdate,
|
||||||
|
} from "@/service/api-admin/api-master-admin";
|
||||||
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
import { Switch } from "react-native-paper";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
|
export default function AdminAppInformation_BusinessFieldDetail() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [data, setData] = useState<any | null>(null);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadDetail();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadDetail = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiAdminMasterBusinessFieldById({
|
||||||
|
id: id as string,
|
||||||
|
category: "sub-bidang",
|
||||||
|
subBidangId: id as string,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Response >>", JSON.stringify(response, null, 2));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
setData(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
setData(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlerSubmit = async () => {
|
||||||
|
if (!data.name) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Lengkapi Data",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const response = await apiAdminMasterBusinessFieldUpdate({
|
||||||
|
id: id as string,
|
||||||
|
data: data,
|
||||||
|
category: "sub-bidang",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal update data",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Data berhasil di update",
|
||||||
|
});
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const buttonSubmit = (
|
||||||
|
<BoxButtonOnFooter>
|
||||||
|
<ButtonCustom
|
||||||
|
disabled={!data?.name}
|
||||||
|
isLoading={isLoading}
|
||||||
|
onPress={() => handlerSubmit()}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</ButtonCustom>
|
||||||
|
</BoxButtonOnFooter>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper footerComponent={buttonSubmit}>
|
||||||
|
<StackCustom>
|
||||||
|
<AdminBackButtonAntTitle title="Update Bidang Bisnis" />
|
||||||
|
|
||||||
|
<TextInputCustom
|
||||||
|
label="Nama Bidang Bisnis"
|
||||||
|
placeholder="Masukan Nama Bidang Bisnis"
|
||||||
|
required
|
||||||
|
value={data?.name}
|
||||||
|
onChangeText={(value) => setData({ ...data, name: value })}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<StackCustom
|
||||||
|
gap={"sm"}
|
||||||
|
style={{
|
||||||
|
alignContent: "flex-start",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextCustom>Status</TextCustom>
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
style={{
|
||||||
|
alignSelf: "flex-start",
|
||||||
|
}}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
value={data?.isActive}
|
||||||
|
onValueChange={(value) => setData({ ...data, isActive: value })}
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,40 +1,81 @@
|
|||||||
import {
|
import {
|
||||||
BoxButtonOnFooter,
|
ActionIcon,
|
||||||
ButtonCustom,
|
BoxButtonOnFooter,
|
||||||
StackCustom,
|
ButtonCustom,
|
||||||
TextInputCustom,
|
CenterCustom,
|
||||||
ViewWrapper,
|
Grid,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_XLARGE } from "@/constants/constans-value";
|
||||||
import { apiAdminMasterBusinessFieldCreate } from "@/service/api-admin/api-master-admin";
|
import { apiAdminMasterBusinessFieldCreate } from "@/service/api-admin/api-master-admin";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import { router } from "expo-router";
|
import { router } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import { Divider } from "react-native-paper";
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminAppInformation_BusinessFieldCreate() {
|
export default function AdminAppInformation_BusinessFieldCreate() {
|
||||||
const [data, setData] = useState<any>({
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [bidang, setBidang] = useState<any>({
|
||||||
name: "",
|
name: "",
|
||||||
});
|
});
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [subBidang, setSubBidang] = useState<any[]>([
|
||||||
|
{
|
||||||
|
name: "",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
const handlerSubmit = async () => {
|
const handlerSubmit = async () => {
|
||||||
if (!data.name) {
|
if (!bidang.name) {
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: "error",
|
type: "error",
|
||||||
text1: "Lengkapi Data",
|
text1: "Lengkapi Data",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (subBidang[0].name === "") {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Lengkapi Sub Bidang",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const response = await apiAdminMasterBusinessFieldCreate({ data: data });
|
|
||||||
|
const newData = {
|
||||||
|
bidang: bidang,
|
||||||
|
subBidang: subBidang,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log("[DATA]", newData);
|
||||||
|
|
||||||
|
const response = await apiAdminMasterBusinessFieldCreate({
|
||||||
|
data: newData,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[RESPONSE]", response);
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: "success",
|
type: "success",
|
||||||
text1: "Data berhasil di tambah",
|
text1: "Data berhasil di tambah",
|
||||||
});
|
});
|
||||||
router.back();
|
// router.back();
|
||||||
|
} else {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal tambah data",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
@@ -50,6 +91,7 @@ export default function AdminAppInformation_BusinessFieldCreate() {
|
|||||||
const buttonSubmit = (
|
const buttonSubmit = (
|
||||||
<BoxButtonOnFooter>
|
<BoxButtonOnFooter>
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
|
disabled={subBidang[0].name === ""}
|
||||||
onPress={() => handlerSubmit()}
|
onPress={() => handlerSubmit()}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
>
|
>
|
||||||
@@ -60,16 +102,70 @@ export default function AdminAppInformation_BusinessFieldCreate() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper footerComponent={buttonSubmit}>
|
<ViewWrapper footerComponent={buttonSubmit}>
|
||||||
<StackCustom>
|
<StackCustom gap={"xs"}>
|
||||||
<AdminBackButtonAntTitle title="Tambah Bidang Bisnis" />
|
<AdminBackButtonAntTitle title="Tambah Bidang Bisnis" />
|
||||||
|
|
||||||
<TextInputCustom
|
<TextInputCustom
|
||||||
label="Nama Bidang Bisnis"
|
label="Nama Bidang Bisnis"
|
||||||
placeholder="Masukan Nama Bidang Bisnis"
|
placeholder="Masukan Nama Bidang Bisnis"
|
||||||
required
|
required
|
||||||
value={data.name}
|
value={bidang.name}
|
||||||
onChangeText={(value) => setData({ ...data, name: value })}
|
onChangeText={(value) => setBidang({ ...bidang, name: value })}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
<Spacing height={5} />
|
||||||
|
|
||||||
|
{subBidang.map((item, index) => (
|
||||||
|
<TextInputCustom
|
||||||
|
key={index}
|
||||||
|
label="Nama Sub Bidang"
|
||||||
|
placeholder="Masukan Nama Sub Bidang"
|
||||||
|
required
|
||||||
|
value={item.name}
|
||||||
|
onChangeText={(value) => {
|
||||||
|
const list = _.clone(subBidang);
|
||||||
|
list[index].name = value;
|
||||||
|
setSubBidang(list);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<CenterCustom>
|
||||||
|
<View
|
||||||
|
style={{ flexDirection: "row", alignItems: "center", gap: 10 }}
|
||||||
|
>
|
||||||
|
<ActionIcon
|
||||||
|
onPress={() => {
|
||||||
|
setSubBidang([...subBidang, { name: "" }]);
|
||||||
|
}}
|
||||||
|
icon={
|
||||||
|
<Ionicons
|
||||||
|
name="add-circle-outline"
|
||||||
|
size={ICON_SIZE_XLARGE}
|
||||||
|
color={MainColor.black}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
size="xl"
|
||||||
|
/>
|
||||||
|
<ActionIcon
|
||||||
|
disabled={subBidang.length <= 1}
|
||||||
|
onPress={() => {
|
||||||
|
const list = _.clone(subBidang);
|
||||||
|
list.pop();
|
||||||
|
setSubBidang(list);
|
||||||
|
}}
|
||||||
|
icon={
|
||||||
|
<Ionicons
|
||||||
|
name="remove-circle-outline"
|
||||||
|
size={ICON_SIZE_XLARGE}
|
||||||
|
color={MainColor.black}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
size="xl"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</CenterCustom>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ const listPage = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "2",
|
id: "2",
|
||||||
label: "Bidang Bisnis",
|
label: "Bidang & Sub Bidang",
|
||||||
value: "business",
|
value: "business",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export default function SuperAdmin_ListUser() {
|
|||||||
</TextCustom>
|
</TextCustom>
|
||||||
}
|
}
|
||||||
component2={
|
component2={
|
||||||
<TextCustom align="center" bold>
|
<TextCustom bold>
|
||||||
Username
|
Username
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,11 +73,7 @@ export default function AdminUserAccess() {
|
|||||||
Aksi
|
Aksi
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
}
|
}
|
||||||
component2={
|
component2={<TextCustom bold>Username</TextCustom>}
|
||||||
<TextCustom align="center" bold>
|
|
||||||
Username
|
|
||||||
</TextCustom>
|
|
||||||
}
|
|
||||||
component3={
|
component3={
|
||||||
<TextCustom align="center" bold>
|
<TextCustom align="center" bold>
|
||||||
Status Akses
|
Status Akses
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
|
import NotificationInitializer from "@/components/_ShareComponent/NotificationInitializer";
|
||||||
import { AuthProvider } from "@/context/AuthContext";
|
import { AuthProvider } from "@/context/AuthContext";
|
||||||
|
import { useForegroundNotifications } from "@/hooks/use-foreground-notifications";
|
||||||
|
import {
|
||||||
|
NotificationProvider,
|
||||||
|
useNotificationStore,
|
||||||
|
} from "@/hooks/use-notification-store";
|
||||||
import AppRoot from "@/screens/RootLayout/AppRoot";
|
import AppRoot from "@/screens/RootLayout/AppRoot";
|
||||||
|
import messaging, {
|
||||||
|
FirebaseMessagingTypes,
|
||||||
|
} from "@react-native-firebase/messaging";
|
||||||
|
import { useEffect } from "react";
|
||||||
import "react-native-gesture-handler";
|
import "react-native-gesture-handler";
|
||||||
import { SafeAreaProvider } from "react-native-safe-area-context";
|
import { SafeAreaProvider } from "react-native-safe-area-context";
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
@@ -7,12 +17,15 @@ import Toast from "react-native-toast-message";
|
|||||||
export default function RootLayout() {
|
export default function RootLayout() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<SafeAreaProvider>
|
<NotificationProvider>
|
||||||
<AuthProvider>
|
<SafeAreaProvider>
|
||||||
<AppRoot />
|
<AuthProvider>
|
||||||
</AuthProvider>
|
<NotificationInitializer />
|
||||||
</SafeAreaProvider>
|
<AppRoot />
|
||||||
<Toast />
|
</AuthProvider>
|
||||||
|
</SafeAreaProvider>
|
||||||
|
<Toast />
|
||||||
|
</NotificationProvider>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ const DateTimeInput_Android: React.FC<DateTimeInputProps> = ({
|
|||||||
const [selectedDate, setSelectedDate] = useState<Date>(value as any);
|
const [selectedDate, setSelectedDate] = useState<Date>(value as any);
|
||||||
const [selectedTime, setSelectedTime] = useState<Date>(value as any);
|
const [selectedTime, setSelectedTime] = useState<Date>(value as any);
|
||||||
|
|
||||||
|
console.log("Date Android", value)
|
||||||
|
|
||||||
// Fungsi untuk menggabungkan tanggal dan waktu
|
// Fungsi untuk menggabungkan tanggal dan waktu
|
||||||
const combineDateAndTime = useCallback((date: Date, time: Date): Date => {
|
const combineDateAndTime = useCallback((date: Date, time: Date): Date => {
|
||||||
const combined = new Date(date);
|
const combined = new Date(date);
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ const DateTimePickerCustom: React.FC<Props> = ({
|
|||||||
minimumDate,
|
minimumDate,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
|
console.log("Date Android Comp", value)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{Platform.OS === "ios" ? (
|
{Platform.OS === "ios" ? (
|
||||||
@@ -47,6 +50,9 @@ const DateTimePickerCustom: React.FC<Props> = ({
|
|||||||
maximumDate={maximumDate}
|
maximumDate={maximumDate}
|
||||||
minimumDate={minimumDate}
|
minimumDate={minimumDate}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
value={value as DateTimePickerEvent | Date | null | any}
|
||||||
|
|
||||||
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export const GridSpan_NewComponent = ({
|
|||||||
style={{
|
style={{
|
||||||
justifyContent: "flex-start",
|
justifyContent: "flex-start",
|
||||||
paddingRight: 5,
|
paddingRight: 5,
|
||||||
paddingLeft: 5,
|
paddingLeft: 3,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{text1}
|
{text1}
|
||||||
|
|||||||
119
components/_ShareComponent/NotificationInitializer.tsx
Normal file
119
components/_ShareComponent/NotificationInitializer.tsx
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
// src/components/NotificationInitializer.tsx
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import messaging from "@react-native-firebase/messaging";
|
||||||
|
import { useForegroundNotifications } from "@/hooks/use-foreground-notifications";
|
||||||
|
import { useNotificationStore } from "@/hooks/use-notification-store";
|
||||||
|
import type { FirebaseMessagingTypes } from "@react-native-firebase/messaging";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
import { Platform } from "react-native";
|
||||||
|
import * as Device from "expo-device";
|
||||||
|
import * as Application from "expo-application";
|
||||||
|
import { apiDeviceRegisterToken } from "@/service/api-notifications";
|
||||||
|
|
||||||
|
|
||||||
|
export default function NotificationInitializer() {
|
||||||
|
// Setup handler notifikasi
|
||||||
|
const { user } = useAuth(); // dari AuthContext
|
||||||
|
const { addNotification } = useNotificationStore();
|
||||||
|
|
||||||
|
// Ambil token FCM (opsional, hanya untuk log)
|
||||||
|
useEffect(() => {
|
||||||
|
if (!user) {
|
||||||
|
console.log("User not available, skipping token sync");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (user?.id) {
|
||||||
|
// syncDeviceToken({ userId: user.id });
|
||||||
|
// }
|
||||||
|
|
||||||
|
const registerDeviceToken = async () => {
|
||||||
|
try {
|
||||||
|
// 1. Minta izin & ambil FCM token
|
||||||
|
if (!messaging().isSupported()) return;
|
||||||
|
const authStatus = await messaging().requestPermission();
|
||||||
|
if (authStatus === messaging.AuthorizationStatus.AUTHORIZED) {
|
||||||
|
const token = await messaging().getToken();
|
||||||
|
console.log("✅ FCM Token:", token);
|
||||||
|
} else {
|
||||||
|
console.warn("Izin notifikasi ditolak");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const fcmToken = await messaging().getToken();
|
||||||
|
if (!fcmToken) {
|
||||||
|
console.warn("Gagal mendapatkan FCM token");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Ambil info device
|
||||||
|
const platform = Platform.OS; // "ios" | "android"
|
||||||
|
// ? await Device.getUdid()
|
||||||
|
// : "unknown";
|
||||||
|
const model = Device.modelName || "unknown";
|
||||||
|
const appVersion =
|
||||||
|
(Application.nativeApplicationVersion || "unknown") +
|
||||||
|
"-" +
|
||||||
|
(Application.nativeBuildVersion || "unknown");
|
||||||
|
const deviceId =
|
||||||
|
Device.osInternalBuildId || Device.modelName + "-" + Date.now();
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"📱 Device info:",
|
||||||
|
JSON.stringify(
|
||||||
|
{
|
||||||
|
fcmToken,
|
||||||
|
platform,
|
||||||
|
deviceId,
|
||||||
|
model,
|
||||||
|
appVersion,
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3. Kirim ke backend
|
||||||
|
await apiDeviceRegisterToken({
|
||||||
|
data: {
|
||||||
|
fcmToken,
|
||||||
|
platform,
|
||||||
|
deviceId,
|
||||||
|
model,
|
||||||
|
appVersion,
|
||||||
|
userId: user?.id || "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("✅ Device token berhasil didaftarkan ke backend");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("❌ Gagal mendaftarkan device token:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
registerDeviceToken();
|
||||||
|
}, [user?.id]);
|
||||||
|
|
||||||
|
const handleForegroundNotification = (
|
||||||
|
message: FirebaseMessagingTypes.RemoteMessage
|
||||||
|
) => {
|
||||||
|
const title = message.notification?.title || "Notifikasi";
|
||||||
|
const body = message.notification?.body || "";
|
||||||
|
const rawData = message.data || {};
|
||||||
|
|
||||||
|
const safeData: Record<string, string> = {};
|
||||||
|
for (const key in rawData) {
|
||||||
|
safeData[key] =
|
||||||
|
typeof rawData[key] === "string"
|
||||||
|
? rawData[key]
|
||||||
|
: JSON.stringify(rawData[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("📥 Menambahkan ke store:", { title, body, safeData });
|
||||||
|
addNotification({ title, body, data: safeData });
|
||||||
|
console.log("✅ Notifikasi ditambahkan ke state");
|
||||||
|
};
|
||||||
|
|
||||||
|
useForegroundNotifications(handleForegroundNotification);
|
||||||
|
|
||||||
|
return null; // komponen ini tidak merender apa-apa
|
||||||
|
}
|
||||||
23
hooks/use-foreground-notifications.ts
Normal file
23
hooks/use-foreground-notifications.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
import messaging, {
|
||||||
|
FirebaseMessagingTypes,
|
||||||
|
} from "@react-native-firebase/messaging";
|
||||||
|
|
||||||
|
// Gunakan tipe resmi dari library
|
||||||
|
type RemoteMessage = FirebaseMessagingTypes.RemoteMessage;
|
||||||
|
|
||||||
|
export function useForegroundNotifications(
|
||||||
|
onMessageReceived: (message: RemoteMessage) => void
|
||||||
|
) {
|
||||||
|
useEffect(() => {
|
||||||
|
const unsubscribe = messaging().onMessage((remoteMessage) => {
|
||||||
|
console.log(
|
||||||
|
"🔔 Notifikasi diterima saat app aktif:",
|
||||||
|
JSON.stringify(remoteMessage, null, 2)
|
||||||
|
);
|
||||||
|
onMessageReceived(remoteMessage);
|
||||||
|
});
|
||||||
|
|
||||||
|
return unsubscribe;
|
||||||
|
}, [onMessageReceived]);
|
||||||
|
}
|
||||||
52
hooks/use-notification-store.tsx
Normal file
52
hooks/use-notification-store.tsx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// hooks/useNotificationStore.ts
|
||||||
|
import { createContext, useContext, useState, ReactNode } from 'react';
|
||||||
|
import type { FirebaseMessagingTypes } from '@react-native-firebase/messaging';
|
||||||
|
|
||||||
|
type AppNotification = {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
body: string;
|
||||||
|
data?: Record<string, string>;
|
||||||
|
read: boolean;
|
||||||
|
timestamp: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const NotificationContext = createContext<{
|
||||||
|
notifications: AppNotification[];
|
||||||
|
addNotification: (notif: Omit<AppNotification, 'id' | 'read' | 'timestamp'>) => void;
|
||||||
|
markAsRead: (id: string) => void;
|
||||||
|
}>({
|
||||||
|
notifications: [],
|
||||||
|
addNotification: () => {},
|
||||||
|
markAsRead: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const NotificationProvider = ({ children }: { children: ReactNode }) => {
|
||||||
|
const [notifications, setNotifications] = useState<AppNotification[]>([]);
|
||||||
|
|
||||||
|
const addNotification = (notif: Omit<AppNotification, 'id' | 'read' | 'timestamp'>) => {
|
||||||
|
setNotifications(prev => [
|
||||||
|
{
|
||||||
|
...notif,
|
||||||
|
id: Date.now().toString(),
|
||||||
|
read: false,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
},
|
||||||
|
...prev,
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const markAsRead = (id: string) => {
|
||||||
|
setNotifications(prev =>
|
||||||
|
prev.map(n => (n.id === id ? { ...n, read: true } : n))
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NotificationContext.Provider value={{ notifications, addNotification, markAsRead }}>
|
||||||
|
{children}
|
||||||
|
</NotificationContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useNotificationStore = () => useContext(NotificationContext);
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,4 +1,5 @@
|
|||||||
import Expo
|
import Expo
|
||||||
|
import FirebaseCore
|
||||||
import React
|
import React
|
||||||
import ReactAppDependencyProvider
|
import ReactAppDependencyProvider
|
||||||
|
|
||||||
@@ -23,6 +24,9 @@ public class AppDelegate: ExpoAppDelegate {
|
|||||||
|
|
||||||
#if os(iOS) || os(tvOS)
|
#if os(iOS) || os(tvOS)
|
||||||
window = UIWindow(frame: UIScreen.main.bounds)
|
window = UIWindow(frame: UIScreen.main.bounds)
|
||||||
|
// @generated begin @react-native-firebase/app-didFinishLaunchingWithOptions - expo prebuild (DO NOT MODIFY) sync-10e8520570672fd76b2403b7e1e27f5198a6349a
|
||||||
|
FirebaseApp.configure()
|
||||||
|
// @generated end @react-native-firebase/app-didFinishLaunchingWithOptions
|
||||||
factory.startReactNative(
|
factory.startReactNative(
|
||||||
withModuleName: "main",
|
withModuleName: "main",
|
||||||
in: window,
|
in: window,
|
||||||
|
|||||||
30
ios/HIPMIBadungConnect/GoogleService-Info.plist
Normal file
30
ios/HIPMIBadungConnect/GoogleService-Info.plist
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>API_KEY</key>
|
||||||
|
<string>AIzaSyAAvM0yBp5kCXa0hLAaNFZNqwkpBGYAWYs</string>
|
||||||
|
<key>GCM_SENDER_ID</key>
|
||||||
|
<string>608461535079</string>
|
||||||
|
<key>PLIST_VERSION</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>BUNDLE_ID</key>
|
||||||
|
<string>com.anonymous.hipmi-mobile</string>
|
||||||
|
<key>PROJECT_ID</key>
|
||||||
|
<string>hipmi-badung-connect</string>
|
||||||
|
<key>STORAGE_BUCKET</key>
|
||||||
|
<string>hipmi-badung-connect.firebasestorage.app</string>
|
||||||
|
<key>IS_ADS_ENABLED</key>
|
||||||
|
<false></false>
|
||||||
|
<key>IS_ANALYTICS_ENABLED</key>
|
||||||
|
<false></false>
|
||||||
|
<key>IS_APPINVITE_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>IS_GCM_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>IS_SIGNIN_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>GOOGLE_APP_ID</key>
|
||||||
|
<string>1:608461535079:ios:589f31b2b6b1068b6761c2</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>13</string>
|
<string>15</string>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
<false/>
|
<false/>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
@@ -55,6 +55,8 @@
|
|||||||
</dict>
|
</dict>
|
||||||
<key>NSCameraUsageDescription</key>
|
<key>NSCameraUsageDescription</key>
|
||||||
<string>Allow $(PRODUCT_NAME) to access your camera</string>
|
<string>Allow $(PRODUCT_NAME) to access your camera</string>
|
||||||
|
<key>NSFaceIDUsageDescription</key>
|
||||||
|
<string>Allow $(PRODUCT_NAME) to access your Face ID biometric data.</string>
|
||||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||||
<string>Allow $(PRODUCT_NAME) to access your location</string>
|
<string>Allow $(PRODUCT_NAME) to access your location</string>
|
||||||
<key>NSLocationAlwaysUsageDescription</key>
|
<key>NSLocationAlwaysUsageDescription</key>
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
<array>
|
<array>
|
||||||
<string>CA92.1</string>
|
<string>CA92.1</string>
|
||||||
|
<string>1C8F.1</string>
|
||||||
|
<string>C56D.1</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
|
|||||||
41
ios/Podfile
41
ios/Podfile
@@ -1,3 +1,5 @@
|
|||||||
|
use_modular_headers!
|
||||||
|
|
||||||
require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
|
require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
|
||||||
require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
|
require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
|
||||||
|
|
||||||
@@ -33,13 +35,14 @@ target 'HIPMIBadungConnect' do
|
|||||||
use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
|
use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
|
||||||
use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']
|
use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']
|
||||||
|
|
||||||
# @generated begin pre_installer - expo prebuild (DO NOT MODIFY) sync-c8812095000d6054b846ce74840f0ffb540c2757
|
# @generated begin pre_installer - expo prebuild (DO NOT MODIFY) sync-c8812095000d6054b846ce74840f0ffb540c2757
|
||||||
pre_install do |installer|
|
pre_install do |installer|
|
||||||
# @generated begin @rnmapbox/maps-pre_installer - expo prebuild (DO NOT MODIFY) sync-ea4905840bf9fcea0acc62e92aa2e784f9d760f8
|
# @generated begin @rnmapbox/maps-pre_installer - expo prebuild (DO NOT MODIFY) sync-ea4905840bf9fcea0acc62e92aa2e784f9d760f8
|
||||||
$RNMapboxMaps.pre_install(installer)
|
$RNMapboxMaps.pre_install(installer)
|
||||||
# @generated end @rnmapbox/maps-pre_installer
|
# @generated end @rnmapbox/maps-pre_installer
|
||||||
end
|
end
|
||||||
# @generated end pre_installer
|
# @generated end pre_installer
|
||||||
|
|
||||||
use_react_native!(
|
use_react_native!(
|
||||||
:path => config[:reactNativePath],
|
:path => config[:reactNativePath],
|
||||||
:hermes_enabled => podfile_properties['expo.jsEngine'] == nil || podfile_properties['expo.jsEngine'] == 'hermes',
|
:hermes_enabled => podfile_properties['expo.jsEngine'] == nil || podfile_properties['expo.jsEngine'] == 'hermes',
|
||||||
@@ -48,10 +51,32 @@ target 'HIPMIBadungConnect' do
|
|||||||
:privacy_file_aggregation_enabled => podfile_properties['apple.privacyManifestAggregationEnabled'] != 'false',
|
:privacy_file_aggregation_enabled => podfile_properties['apple.privacyManifestAggregationEnabled'] != 'false',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
pod 'Firebase'
|
||||||
|
pod 'Firebase/Messaging'
|
||||||
|
|
||||||
|
# @generated begin post_installer - expo prebuild (DO NOT MODIFY) sync-4092f82b887b5b9edb84642c2a56984d69b9a403
|
||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
# @generated begin @rnmapbox/maps-post_installer - expo prebuild (DO NOT MODIFY) sync-c4e8f90e96f6b6c6ea9241dd7b52ab5f57f7bf36
|
# @generated begin @rnmapbox/maps-post_installer - expo prebuild (DO NOT MODIFY) sync-c4e8f90e96f6b6c6ea9241dd7b52ab5f57f7bf36
|
||||||
$RNMapboxMaps.post_install(installer)
|
$RNMapboxMaps.post_install(installer)
|
||||||
# @generated end @rnmapbox/maps-post_installer
|
# @generated end @rnmapbox/maps-post_installer
|
||||||
|
|
||||||
|
# Fix all script phases with incorrect paths
|
||||||
|
installer.pods_project.targets.each do |target|
|
||||||
|
target.build_phases.each do |phase|
|
||||||
|
next unless phase.respond_to?(:shell_script)
|
||||||
|
|
||||||
|
# Fix duplicated path issue
|
||||||
|
if phase.shell_script.include?('with-environment.sh')
|
||||||
|
# Remove any existing path and use proper relative path
|
||||||
|
phase.shell_script = phase.shell_script.gsub(
|
||||||
|
%r{(/.*?/node_modules/react-native)+/scripts/xcode/with-environment.sh},
|
||||||
|
'${PODS_ROOT}/../../node_modules/react-native/scripts/xcode/with-environment.sh'
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Standard React Native post install
|
||||||
react_native_post_install(
|
react_native_post_install(
|
||||||
installer,
|
installer,
|
||||||
config[:reactNativePath],
|
config[:reactNativePath],
|
||||||
@@ -59,4 +84,6 @@ target 'HIPMIBadungConnect' do
|
|||||||
:ccache_enabled => podfile_properties['apple.ccacheEnabled'] == 'true',
|
:ccache_enabled => podfile_properties['apple.ccacheEnabled'] == 'true',
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
# @generated end post_installer
|
||||||
|
|
||||||
|
end
|
||||||
177
ios/Podfile.lock
177
ios/Podfile.lock
@@ -239,6 +239,8 @@ PODS:
|
|||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoKeepAwake (15.0.7):
|
- ExpoKeepAwake (15.0.7):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
|
- ExpoLinearGradient (15.0.7):
|
||||||
|
- ExpoModulesCore
|
||||||
- ExpoLinking (8.0.8):
|
- ExpoLinking (8.0.8):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- ExpoLocation (19.0.7):
|
- ExpoLocation (19.0.7):
|
||||||
@@ -277,6 +279,113 @@ PODS:
|
|||||||
- EXUpdatesInterface (2.0.0):
|
- EXUpdatesInterface (2.0.0):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- FBLazyVector (0.81.4)
|
- FBLazyVector (0.81.4)
|
||||||
|
- Firebase (12.6.0):
|
||||||
|
- Firebase/Core (= 12.6.0)
|
||||||
|
- Firebase/Core (12.6.0):
|
||||||
|
- Firebase/CoreOnly
|
||||||
|
- FirebaseAnalytics (~> 12.6.0)
|
||||||
|
- Firebase/CoreOnly (12.6.0):
|
||||||
|
- FirebaseCore (~> 12.6.0)
|
||||||
|
- Firebase/Messaging (12.6.0):
|
||||||
|
- Firebase/CoreOnly
|
||||||
|
- FirebaseMessaging (~> 12.6.0)
|
||||||
|
- FirebaseAnalytics (12.6.0):
|
||||||
|
- FirebaseAnalytics/Default (= 12.6.0)
|
||||||
|
- FirebaseCore (~> 12.6.0)
|
||||||
|
- FirebaseInstallations (~> 12.6.0)
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
|
- nanopb (~> 3.30910.0)
|
||||||
|
- FirebaseAnalytics/Default (12.6.0):
|
||||||
|
- FirebaseCore (~> 12.6.0)
|
||||||
|
- FirebaseInstallations (~> 12.6.0)
|
||||||
|
- GoogleAppMeasurement/Default (= 12.6.0)
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
|
- nanopb (~> 3.30910.0)
|
||||||
|
- FirebaseCore (12.6.0):
|
||||||
|
- FirebaseCoreInternal (~> 12.6.0)
|
||||||
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
|
- GoogleUtilities/Logger (~> 8.1)
|
||||||
|
- FirebaseCoreExtension (12.6.0):
|
||||||
|
- FirebaseCore (~> 12.6.0)
|
||||||
|
- FirebaseCoreInternal (12.6.0):
|
||||||
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
|
- FirebaseInstallations (12.6.0):
|
||||||
|
- FirebaseCore (~> 12.6.0)
|
||||||
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
|
- PromisesObjC (~> 2.4)
|
||||||
|
- FirebaseMessaging (12.6.0):
|
||||||
|
- FirebaseCore (~> 12.6.0)
|
||||||
|
- FirebaseInstallations (~> 12.6.0)
|
||||||
|
- GoogleDataTransport (~> 10.1)
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
|
- GoogleUtilities/Reachability (~> 8.1)
|
||||||
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
|
- nanopb (~> 3.30910.0)
|
||||||
|
- GoogleAdsOnDeviceConversion (3.2.0):
|
||||||
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
|
- GoogleUtilities/Logger (~> 8.1)
|
||||||
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
|
- nanopb (~> 3.30910.0)
|
||||||
|
- GoogleAppMeasurement/Core (12.6.0):
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
|
- nanopb (~> 3.30910.0)
|
||||||
|
- GoogleAppMeasurement/Default (12.6.0):
|
||||||
|
- GoogleAdsOnDeviceConversion (~> 3.2.0)
|
||||||
|
- GoogleAppMeasurement/Core (= 12.6.0)
|
||||||
|
- GoogleAppMeasurement/IdentitySupport (= 12.6.0)
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
|
- nanopb (~> 3.30910.0)
|
||||||
|
- GoogleAppMeasurement/IdentitySupport (12.6.0):
|
||||||
|
- GoogleAppMeasurement/Core (= 12.6.0)
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
|
- nanopb (~> 3.30910.0)
|
||||||
|
- GoogleDataTransport (10.1.0):
|
||||||
|
- nanopb (~> 3.30910.0)
|
||||||
|
- PromisesObjC (~> 2.4)
|
||||||
|
- GoogleUtilities/AppDelegateSwizzler (8.1.0):
|
||||||
|
- GoogleUtilities/Environment
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- GoogleUtilities/Network
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
|
- GoogleUtilities/Environment (8.1.0):
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
|
- GoogleUtilities/Logger (8.1.0):
|
||||||
|
- GoogleUtilities/Environment
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
|
- GoogleUtilities/MethodSwizzler (8.1.0):
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
|
- GoogleUtilities/Network (8.1.0):
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- "GoogleUtilities/NSData+zlib"
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
|
- GoogleUtilities/Reachability
|
||||||
|
- "GoogleUtilities/NSData+zlib (8.1.0)":
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
|
- GoogleUtilities/Privacy (8.1.0)
|
||||||
|
- GoogleUtilities/Reachability (8.1.0):
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
|
- GoogleUtilities/UserDefaults (8.1.0):
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
- hermes-engine (0.81.4):
|
- hermes-engine (0.81.4):
|
||||||
- hermes-engine/Pre-built (= 0.81.4)
|
- hermes-engine/Pre-built (= 0.81.4)
|
||||||
- hermes-engine/Pre-built (0.81.4)
|
- hermes-engine/Pre-built (0.81.4)
|
||||||
@@ -305,6 +414,12 @@ PODS:
|
|||||||
- MapboxCommon (= 24.15.4)
|
- MapboxCommon (= 24.15.4)
|
||||||
- MapboxCoreMaps (= 11.15.4)
|
- MapboxCoreMaps (= 11.15.4)
|
||||||
- Turf (= 4.0.0)
|
- Turf (= 4.0.0)
|
||||||
|
- nanopb (3.30910.0):
|
||||||
|
- nanopb/decode (= 3.30910.0)
|
||||||
|
- nanopb/encode (= 3.30910.0)
|
||||||
|
- nanopb/decode (3.30910.0)
|
||||||
|
- nanopb/encode (3.30910.0)
|
||||||
|
- PromisesObjC (2.4.0)
|
||||||
- RCTDeprecation (0.81.4)
|
- RCTDeprecation (0.81.4)
|
||||||
- RCTRequired (0.81.4)
|
- RCTRequired (0.81.4)
|
||||||
- RCTTypeSafety (0.81.4):
|
- RCTTypeSafety (0.81.4):
|
||||||
@@ -2138,6 +2253,14 @@ PODS:
|
|||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- ReactNativeDependencies
|
- ReactNativeDependencies
|
||||||
- Yoga
|
- Yoga
|
||||||
|
- RNFBApp (23.7.0):
|
||||||
|
- Firebase/CoreOnly (= 12.6.0)
|
||||||
|
- React-Core
|
||||||
|
- RNFBMessaging (23.7.0):
|
||||||
|
- Firebase/Messaging (= 12.6.0)
|
||||||
|
- FirebaseCoreExtension
|
||||||
|
- React-Core
|
||||||
|
- RNFBApp
|
||||||
- RNGestureHandler (2.28.0):
|
- RNGestureHandler (2.28.0):
|
||||||
- hermes-engine
|
- hermes-engine
|
||||||
- RCTRequired
|
- RCTRequired
|
||||||
@@ -2446,10 +2569,10 @@ PODS:
|
|||||||
- ReactCommon/turbomodule/core
|
- ReactCommon/turbomodule/core
|
||||||
- ReactNativeDependencies
|
- ReactNativeDependencies
|
||||||
- Yoga
|
- Yoga
|
||||||
- SDWebImage (5.21.1):
|
- SDWebImage (5.21.3):
|
||||||
- SDWebImage/Core (= 5.21.1)
|
- SDWebImage/Core (= 5.21.3)
|
||||||
- SDWebImage/Core (5.21.1)
|
- SDWebImage/Core (5.21.3)
|
||||||
- SDWebImageAVIFCoder (0.11.0):
|
- SDWebImageAVIFCoder (0.11.1):
|
||||||
- libavif/core (>= 0.11.0)
|
- libavif/core (>= 0.11.0)
|
||||||
- SDWebImage (~> 5.10)
|
- SDWebImage (~> 5.10)
|
||||||
- SDWebImageSVGCoder (1.7.0):
|
- SDWebImageSVGCoder (1.7.0):
|
||||||
@@ -2489,6 +2612,7 @@ DEPENDENCIES:
|
|||||||
- ExpoImage (from `../node_modules/expo-image/ios`)
|
- ExpoImage (from `../node_modules/expo-image/ios`)
|
||||||
- ExpoImagePicker (from `../node_modules/expo-image-picker/ios`)
|
- ExpoImagePicker (from `../node_modules/expo-image-picker/ios`)
|
||||||
- ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`)
|
- ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`)
|
||||||
|
- ExpoLinearGradient (from `../node_modules/expo-linear-gradient/ios`)
|
||||||
- ExpoLinking (from `../node_modules/expo-linking/ios`)
|
- ExpoLinking (from `../node_modules/expo-linking/ios`)
|
||||||
- ExpoLocation (from `../node_modules/expo-location/ios`)
|
- ExpoLocation (from `../node_modules/expo-location/ios`)
|
||||||
- ExpoModulesCore (from `../node_modules/expo-modules-core`)
|
- ExpoModulesCore (from `../node_modules/expo-modules-core`)
|
||||||
@@ -2498,6 +2622,8 @@ DEPENDENCIES:
|
|||||||
- ExpoWebBrowser (from `../node_modules/expo-web-browser/ios`)
|
- ExpoWebBrowser (from `../node_modules/expo-web-browser/ios`)
|
||||||
- EXUpdatesInterface (from `../node_modules/expo-updates-interface/ios`)
|
- EXUpdatesInterface (from `../node_modules/expo-updates-interface/ios`)
|
||||||
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
|
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
|
||||||
|
- Firebase
|
||||||
|
- Firebase/Messaging
|
||||||
- hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
|
- hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
|
||||||
- RCTDeprecation (from `../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`)
|
- RCTDeprecation (from `../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`)
|
||||||
- RCTRequired (from `../node_modules/react-native/Libraries/Required`)
|
- RCTRequired (from `../node_modules/react-native/Libraries/Required`)
|
||||||
@@ -2571,6 +2697,8 @@ DEPENDENCIES:
|
|||||||
- ReactNativeDependencies (from `../node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec`)
|
- ReactNativeDependencies (from `../node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec`)
|
||||||
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
|
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
|
||||||
- "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)"
|
- "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)"
|
||||||
|
- "RNFBApp (from `../node_modules/@react-native-firebase/app`)"
|
||||||
|
- "RNFBMessaging (from `../node_modules/@react-native-firebase/messaging`)"
|
||||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||||
- "rnmapbox-maps (from `../node_modules/@rnmapbox/maps`)"
|
- "rnmapbox-maps (from `../node_modules/@rnmapbox/maps`)"
|
||||||
- RNReanimated (from `../node_modules/react-native-reanimated`)
|
- RNReanimated (from `../node_modules/react-native-reanimated`)
|
||||||
@@ -2582,12 +2710,25 @@ DEPENDENCIES:
|
|||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
|
- Firebase
|
||||||
|
- FirebaseAnalytics
|
||||||
|
- FirebaseCore
|
||||||
|
- FirebaseCoreExtension
|
||||||
|
- FirebaseCoreInternal
|
||||||
|
- FirebaseInstallations
|
||||||
|
- FirebaseMessaging
|
||||||
|
- GoogleAdsOnDeviceConversion
|
||||||
|
- GoogleAppMeasurement
|
||||||
|
- GoogleDataTransport
|
||||||
|
- GoogleUtilities
|
||||||
- libavif
|
- libavif
|
||||||
- libdav1d
|
- libdav1d
|
||||||
- libwebp
|
- libwebp
|
||||||
- MapboxCommon
|
- MapboxCommon
|
||||||
- MapboxCoreMaps
|
- MapboxCoreMaps
|
||||||
- MapboxMaps
|
- MapboxMaps
|
||||||
|
- nanopb
|
||||||
|
- PromisesObjC
|
||||||
- SDWebImage
|
- SDWebImage
|
||||||
- SDWebImageAVIFCoder
|
- SDWebImageAVIFCoder
|
||||||
- SDWebImageSVGCoder
|
- SDWebImageSVGCoder
|
||||||
@@ -2642,6 +2783,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../node_modules/expo-image-picker/ios"
|
:path: "../node_modules/expo-image-picker/ios"
|
||||||
ExpoKeepAwake:
|
ExpoKeepAwake:
|
||||||
:path: "../node_modules/expo-keep-awake/ios"
|
:path: "../node_modules/expo-keep-awake/ios"
|
||||||
|
ExpoLinearGradient:
|
||||||
|
:path: "../node_modules/expo-linear-gradient/ios"
|
||||||
ExpoLinking:
|
ExpoLinking:
|
||||||
:path: "../node_modules/expo-linking/ios"
|
:path: "../node_modules/expo-linking/ios"
|
||||||
ExpoLocation:
|
ExpoLocation:
|
||||||
@@ -2805,6 +2948,10 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../node_modules/@react-native-async-storage/async-storage"
|
:path: "../node_modules/@react-native-async-storage/async-storage"
|
||||||
RNDateTimePicker:
|
RNDateTimePicker:
|
||||||
:path: "../node_modules/@react-native-community/datetimepicker"
|
:path: "../node_modules/@react-native-community/datetimepicker"
|
||||||
|
RNFBApp:
|
||||||
|
:path: "../node_modules/@react-native-firebase/app"
|
||||||
|
RNFBMessaging:
|
||||||
|
:path: "../node_modules/@react-native-firebase/messaging"
|
||||||
RNGestureHandler:
|
RNGestureHandler:
|
||||||
:path: "../node_modules/react-native-gesture-handler"
|
:path: "../node_modules/react-native-gesture-handler"
|
||||||
rnmapbox-maps:
|
rnmapbox-maps:
|
||||||
@@ -2846,6 +2993,7 @@ SPEC CHECKSUMS:
|
|||||||
ExpoImage: e88f500585913969b930e13a4be47277eb7c6de8
|
ExpoImage: e88f500585913969b930e13a4be47277eb7c6de8
|
||||||
ExpoImagePicker: d251aab45a1b1857e4156fed88511b278b4eee1c
|
ExpoImagePicker: d251aab45a1b1857e4156fed88511b278b4eee1c
|
||||||
ExpoKeepAwake: 1a2e820692e933c94a565ec3fbbe38ac31658ffe
|
ExpoKeepAwake: 1a2e820692e933c94a565ec3fbbe38ac31658ffe
|
||||||
|
ExpoLinearGradient: a464898cb95153125e3b81894fd479bcb1c7dd27
|
||||||
ExpoLinking: f051f28e50ea9269ff539317c166adec81d9342d
|
ExpoLinking: f051f28e50ea9269ff539317c166adec81d9342d
|
||||||
ExpoLocation: 93d7faa0c2adbd5a04686af0c1a61bc6ed3ee2f7
|
ExpoLocation: 93d7faa0c2adbd5a04686af0c1a61bc6ed3ee2f7
|
||||||
ExpoModulesCore: 9281d8f1cda9d0c37dbce34c26014212b22eb8c0
|
ExpoModulesCore: 9281d8f1cda9d0c37dbce34c26014212b22eb8c0
|
||||||
@@ -2855,6 +3003,17 @@ SPEC CHECKSUMS:
|
|||||||
ExpoWebBrowser: b973e1351fdcf5fec0c400997b1851f5a8219ec3
|
ExpoWebBrowser: b973e1351fdcf5fec0c400997b1851f5a8219ec3
|
||||||
EXUpdatesInterface: 5adf50cb41e079c861da6d9b4b954c3db9a50734
|
EXUpdatesInterface: 5adf50cb41e079c861da6d9b4b954c3db9a50734
|
||||||
FBLazyVector: 9e0cd874afd81d9a4d36679daca991b58b260d42
|
FBLazyVector: 9e0cd874afd81d9a4d36679daca991b58b260d42
|
||||||
|
Firebase: a451a7b61536298fd5cbfe3a746fd40443a50679
|
||||||
|
FirebaseAnalytics: d0a97a0db6425e5a5d966340b87f92ca7b13a557
|
||||||
|
FirebaseCore: 0e38ad5d62d980a47a64b8e9301ffa311457be04
|
||||||
|
FirebaseCoreExtension: 032fd6f8509e591fda8cb76f6651f20d926b121f
|
||||||
|
FirebaseCoreInternal: 69bf1306a05b8ac43004f6cc1f804bb7b05b229e
|
||||||
|
FirebaseInstallations: 631b38da2e11a83daa4bfb482f79d286a5dfa7ad
|
||||||
|
FirebaseMessaging: a61bc42dcab3f7a346d94bbb54dab2c9435b18b2
|
||||||
|
GoogleAdsOnDeviceConversion: d68c69dd9581a0f5da02617b6f377e5be483970f
|
||||||
|
GoogleAppMeasurement: 3bf40aff49a601af5da1c3345702fcb4991d35ee
|
||||||
|
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||||
|
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||||
hermes-engine: 35c763d57c9832d0eef764316ca1c4d043581394
|
hermes-engine: 35c763d57c9832d0eef764316ca1c4d043581394
|
||||||
libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7
|
libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7
|
||||||
libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f
|
libdav1d: 23581a4d8ec811ff171ed5e2e05cd27bad64c39f
|
||||||
@@ -2862,6 +3021,8 @@ SPEC CHECKSUMS:
|
|||||||
MapboxCommon: 975faa94b893bb64a1d28b09d9d6d820e1030a26
|
MapboxCommon: 975faa94b893bb64a1d28b09d9d6d820e1030a26
|
||||||
MapboxCoreMaps: 105af9894d850290fbb466e9f9a133f5d175abf1
|
MapboxCoreMaps: 105af9894d850290fbb466e9f9a133f5d175abf1
|
||||||
MapboxMaps: e97e59d6ba48bb6f695a4c1dc2f174cb24743cd4
|
MapboxMaps: e97e59d6ba48bb6f695a4c1dc2f174cb24743cd4
|
||||||
|
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||||
|
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||||
RCTDeprecation: 7487d6dda857ccd4cb3dd6ecfccdc3170e85dcbc
|
RCTDeprecation: 7487d6dda857ccd4cb3dd6ecfccdc3170e85dcbc
|
||||||
RCTRequired: 54128b7df8be566881d48c7234724a78cb9b6157
|
RCTRequired: 54128b7df8be566881d48c7234724a78cb9b6157
|
||||||
RCTTypeSafety: d2b07797a79e45d7b19e1cd2f53c79ab419fe217
|
RCTTypeSafety: d2b07797a79e45d7b19e1cd2f53c79ab419fe217
|
||||||
@@ -2933,6 +3094,8 @@ SPEC CHECKSUMS:
|
|||||||
ReactNativeDependencies: ed6d1e64802b150399f04f1d5728ec16b437251e
|
ReactNativeDependencies: ed6d1e64802b150399f04f1d5728ec16b437251e
|
||||||
RNCAsyncStorage: 3a4f5e2777dae1688b781a487923a08569e27fe4
|
RNCAsyncStorage: 3a4f5e2777dae1688b781a487923a08569e27fe4
|
||||||
RNDateTimePicker: be0e44bcb9ed0607c7c5f47dbedd88cf091f6791
|
RNDateTimePicker: be0e44bcb9ed0607c7c5f47dbedd88cf091f6791
|
||||||
|
RNFBApp: 0c4cadae3900893d4631ea9a9effd14f853cd8e0
|
||||||
|
RNFBMessaging: 873220424f6f6aa5c787baf5c7099e1e2ba087c9
|
||||||
RNGestureHandler: 2914750df066d89bf9d8f48a10ad5f0051108ac3
|
RNGestureHandler: 2914750df066d89bf9d8f48a10ad5f0051108ac3
|
||||||
rnmapbox-maps: 3c20ce786a7991498445c32de4fe4244e32aa0ee
|
rnmapbox-maps: 3c20ce786a7991498445c32de4fe4244e32aa0ee
|
||||||
RNReanimated: 8d3a14606ad49f022c17d9e12a2d339e9e5ad9b0
|
RNReanimated: 8d3a14606ad49f022c17d9e12a2d339e9e5ad9b0
|
||||||
@@ -2940,14 +3103,14 @@ SPEC CHECKSUMS:
|
|||||||
RNSVG: 31d6639663c249b7d5abc9728dde2041eb2a3c34
|
RNSVG: 31d6639663c249b7d5abc9728dde2041eb2a3c34
|
||||||
RNVectorIcons: 704d89d2f11886824e3bd5cbea34dd00aeade200
|
RNVectorIcons: 704d89d2f11886824e3bd5cbea34dd00aeade200
|
||||||
RNWorklets: 76fce72926e28e304afb44f0da23b2d24f2c1fa0
|
RNWorklets: 76fce72926e28e304afb44f0da23b2d24f2c1fa0
|
||||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a
|
||||||
SDWebImageAVIFCoder: 00310d246aab3232ce77f1d8f0076f8c4b021d90
|
SDWebImageAVIFCoder: afe194a084e851f70228e4be35ef651df0fc5c57
|
||||||
SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c
|
SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c
|
||||||
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
|
SDWebImageWebPCoder: e38c0a70396191361d60c092933e22c20d5b1380
|
||||||
Turf: c9eb11a65d96af58cac523460fd40fec5061b081
|
Turf: c9eb11a65d96af58cac523460fd40fec5061b081
|
||||||
Yoga: 051f086b5ccf465ff2ed38a2cf5a558ae01aaaa1
|
Yoga: 051f086b5ccf465ff2ed38a2cf5a558ae01aaaa1
|
||||||
ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5
|
ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5
|
||||||
|
|
||||||
PODFILE CHECKSUM: 961e5122c387eef49538723a9e3e7a469ca4144f
|
PODFILE CHECKSUM: 9c1ecbc7e57ca21dc7c93635b18e66f8f6d7bdd9
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
"@expo/vector-icons": "^15.0.2",
|
"@expo/vector-icons": "^15.0.2",
|
||||||
"@react-native-async-storage/async-storage": "2.2.0",
|
"@react-native-async-storage/async-storage": "2.2.0",
|
||||||
"@react-native-community/datetimepicker": "8.4.4",
|
"@react-native-community/datetimepicker": "8.4.4",
|
||||||
|
"@react-native-firebase/app": "^23.7.0",
|
||||||
|
"@react-native-firebase/messaging": "^23.7.0",
|
||||||
"@react-navigation/bottom-tabs": "^7.3.10",
|
"@react-navigation/bottom-tabs": "^7.3.10",
|
||||||
"@react-navigation/drawer": "^7.3.9",
|
"@react-navigation/drawer": "^7.3.9",
|
||||||
"@react-navigation/elements": "^2.3.8",
|
"@react-navigation/elements": "^2.3.8",
|
||||||
@@ -72,6 +74,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
|
"@react-native-community/cli": "^20.0.2",
|
||||||
"@types/react": "~19.1.10",
|
"@types/react": "~19.1.10",
|
||||||
"eslint": "^9.25.0",
|
"eslint": "^9.25.0",
|
||||||
"eslint-config-expo": "~10.0.0",
|
"eslint-config-expo": "~10.0.0",
|
||||||
|
|||||||
@@ -134,10 +134,10 @@ export default function LoginView() {
|
|||||||
|
|
||||||
if (token && token !== "" && isAdmin) {
|
if (token && token !== "" && isAdmin) {
|
||||||
// Akan di aktifkan jika sudah losos review
|
// Akan di aktifkan jika sudah losos review
|
||||||
return <Redirect href={"/(application)/admin/dashboard"} />;
|
// return <Redirect href={"/(application)/admin/dashboard"} />;
|
||||||
|
|
||||||
// Sementara gunakan ini
|
// Sementara gunakan ini
|
||||||
// return <Redirect href={"/(application)/(user)/home"} />;
|
return <Redirect href={"/(application)/(user)/home"} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export default function Event_BoxPublishSection({
|
|||||||
<AvatarUsernameAndOtherComponent
|
<AvatarUsernameAndOtherComponent
|
||||||
avatarHref={`/profile/${data?.Author?.Profile?.id}`}
|
avatarHref={`/profile/${data?.Author?.Profile?.id}`}
|
||||||
name={data?.Author?.username || "-"}
|
name={data?.Author?.username || "-"}
|
||||||
rightComponent={rightComponentAvatar}
|
// rightComponent={rightComponentAvatar}
|
||||||
avatar={data?.Author?.Profile?.imageId || ""}
|
avatar={data?.Author?.Profile?.imageId || ""}
|
||||||
/>
|
/>
|
||||||
<TextCustom truncate bold>
|
<TextCustom truncate bold>
|
||||||
|
|||||||
45
screens/Home/HeaderBell.tsx
Normal file
45
screens/Home/HeaderBell.tsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// components/HeaderBell.tsx
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { View, Text } from "react-native";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { useNotificationStore } from "@/hooks/use-notification-store";
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
|
||||||
|
export default function HeaderBell() {
|
||||||
|
const { notifications } = useNotificationStore();
|
||||||
|
const unreadCount = notifications.filter((n) => !n.read).length;
|
||||||
|
console.log("NOTIF:", JSON.stringify(notifications, null, 2));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{ position: "relative" }}>
|
||||||
|
<Ionicons
|
||||||
|
name="notifications"
|
||||||
|
size={20}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
onPress={() => {
|
||||||
|
router.push("/notifications");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{unreadCount > 0 && (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: -4,
|
||||||
|
right: -4,
|
||||||
|
backgroundColor: "red",
|
||||||
|
borderRadius: 8,
|
||||||
|
minWidth: 16,
|
||||||
|
height: 16,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
paddingHorizontal: 2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text style={{ color: "white", fontSize: 10, fontWeight: "bold" }}>
|
||||||
|
{unreadCount > 9 ? "9+" : unreadCount}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ export default function Home_FeatureSection() {
|
|||||||
name: "Collaboration",
|
name: "Collaboration",
|
||||||
icon: <Ionicons name="share" size={48} color="gray" />,
|
icon: <Ionicons name="share" size={48} color="gray" />,
|
||||||
onPress: () => router.push("/(application)/(user)/collaboration/(tabs)"),
|
onPress: () => router.push("/(application)/(user)/collaboration/(tabs)"),
|
||||||
status: "active",
|
status: "inactive",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Voting",
|
name: "Voting",
|
||||||
|
|||||||
@@ -60,10 +60,20 @@ export async function apiAdminMasterBusinessField() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function apiAdminMasterBusinessFieldById({ id }: { id: string }) {
|
export async function apiAdminMasterBusinessFieldById({
|
||||||
|
id,
|
||||||
|
subBidangId,
|
||||||
|
category,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
subBidangId?: string | null;
|
||||||
|
category: "bidang" | "sub-bidang" | "all";
|
||||||
|
}) {
|
||||||
|
const queryCategory = category ? `?category=${category}` : "";
|
||||||
|
const querySubBidang = subBidangId ? `&subBidangId=${subBidangId}` : "";
|
||||||
try {
|
try {
|
||||||
const response = await apiConfig.get(
|
const response = await apiConfig.get(
|
||||||
`/mobile/admin/master/business-field/${id}`
|
`/mobile/admin/master/business-field/${id}${queryCategory}${querySubBidang}`
|
||||||
);
|
);
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -74,13 +84,15 @@ export async function apiAdminMasterBusinessFieldById({ id }: { id: string }) {
|
|||||||
export async function apiAdminMasterBusinessFieldUpdate({
|
export async function apiAdminMasterBusinessFieldUpdate({
|
||||||
id,
|
id,
|
||||||
data,
|
data,
|
||||||
|
category,
|
||||||
}: {
|
}: {
|
||||||
id: string;
|
id: string;
|
||||||
data: any;
|
data: any;
|
||||||
|
category: "bidang" | "sub-bidang";
|
||||||
}) {
|
}) {
|
||||||
try {
|
try {
|
||||||
const response = await apiConfig.put(
|
const response = await apiConfig.put(
|
||||||
`/mobile/admin/master/business-field/${id}`,
|
`/mobile/admin/master/business-field/${id}?category=${category}`,
|
||||||
{
|
{
|
||||||
data: data,
|
data: data,
|
||||||
}
|
}
|
||||||
@@ -179,7 +191,11 @@ export async function apiAdminMasterDonationCategory() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function apiAdminMasterDonationCategoryById({ id }: { id: string }) {
|
export async function apiAdminMasterDonationCategoryById({
|
||||||
|
id,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
}) {
|
||||||
try {
|
try {
|
||||||
const response = await apiConfig.get(`/mobile/admin/master/donation/${id}`);
|
const response = await apiConfig.get(`/mobile/admin/master/donation/${id}`);
|
||||||
return response.data;
|
return response.data;
|
||||||
@@ -208,7 +224,11 @@ export async function apiAdminMasterDonationCategoryUpdate({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function apiAdminMasterDonationCategoryCreate({ data }: { data: any }) {
|
export async function apiAdminMasterDonationCategoryCreate({
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
data: any;
|
||||||
|
}) {
|
||||||
try {
|
try {
|
||||||
const response = await apiConfig.post(`/mobile/admin/master/donation`, {
|
const response = await apiConfig.post(`/mobile/admin/master/donation`, {
|
||||||
data: data,
|
data: data,
|
||||||
@@ -219,4 +239,4 @@ export async function apiAdminMasterDonationCategoryCreate({ data }: { data: any
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================== END DONATION ================== //
|
// ================== END DONATION ================== //
|
||||||
|
|||||||
51
service/api-notifications.ts
Normal file
51
service/api-notifications.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import { apiConfig } from "./api-config";
|
||||||
|
|
||||||
|
type NotificationProp = {
|
||||||
|
fcmToken: string;
|
||||||
|
title: string;
|
||||||
|
body: Object;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function apiNotificationsSend({
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
data: NotificationProp;
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.post(`/mobile/notifications`, {
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Fecth Notif", response.data);
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeviceTokenData = {
|
||||||
|
fcmToken: string;
|
||||||
|
platform: string;
|
||||||
|
deviceId: string;
|
||||||
|
model: string;
|
||||||
|
appVersion: string;
|
||||||
|
userId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function apiDeviceRegisterToken({
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
data: DeviceTokenData;
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.post(`/mobile/auth/device-tokens`, {
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
console.log("Device token registered:", response.data);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to register device token:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user