Compare commits
25 Commits
main
...
notificati
| Author | SHA1 | Date | |
|---|---|---|---|
| da82a02a45 | |||
| 14c0f0e499 | |||
| 0262423c50 | |||
| c2682246d6 | |||
| 465e01015e | |||
| 3b15871ad4 | |||
| 9123e73606 | |||
| 6e2046467f | |||
| ca33dd83bb | |||
| ea3fbdc541 | |||
| 33cd47aaed | |||
| 57ac1eb45e | |||
| 145ad73616 | |||
| 7c85e35c61 | |||
| d098b8ca16 | |||
| 73a473cdc7 | |||
| 3f85f330d2 | |||
| 7743a2467c | |||
| 54611ef812 | |||
| 1503707eed | |||
| a01a9bd93f | |||
| 05c1cac10f | |||
| d27c01ed56 | |||
| 34680a4c38 | |||
| 43c8c105cf |
@@ -100,7 +100,7 @@ packagingOptions {
|
|||||||
applicationId 'com.bip.hipmimobileapp'
|
applicationId 'com.bip.hipmimobileapp'
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 3
|
versionCode 4
|
||||||
versionName "1.0.1"
|
versionName "1.0.1"
|
||||||
|
|
||||||
buildConfigField "String", "REACT_NATIVE_RELEASE_LEVEL", "\"${findProperty('reactNativeReleaseLevel') ?: 'stable'}\""
|
buildConfigField "String", "REACT_NATIVE_RELEASE_LEVEL", "\"${findProperty('reactNativeReleaseLevel') ?: 'stable'}\""
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
<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_color" android:resource="@color/notification_icon_color" tools:replace="android:resource"/>
|
||||||
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon"/>
|
<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_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.notifications.default_notification_icon" android:resource="@drawable/notification_icon"/>
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<full-backup-content>
|
||||||
|
<exclude domain="sharedpref" path="SECURESTORE"/>
|
||||||
|
</full-backup-content>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<data-extraction-rules>
|
||||||
|
<cloud-backup>
|
||||||
|
<exclude domain="sharedpref" path="SECURESTORE"/>
|
||||||
|
</cloud-backup>
|
||||||
|
<device-transfer>
|
||||||
|
<exclude domain="sharedpref" path="SECURESTORE"/>
|
||||||
|
</device-transfer>
|
||||||
|
</data-extraction-rules>
|
||||||
@@ -6,7 +6,7 @@ buildscript {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.google.gms:google-services:4.4.1'
|
classpath 'com.google.gms:google-services:4.4.1'
|
||||||
classpath('com.android.tools.build:gradle')
|
classpath('com.android.tools.build:gradle')
|
||||||
classpath('com.facebook.react:react-native-gradle-plugin')
|
classpath('com.facebook.react:react-native-gradle-plugin')
|
||||||
classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')
|
classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default {
|
|||||||
"Aplikasi membutuhkan akses lokasi untuk menampilkan peta.",
|
"Aplikasi membutuhkan akses lokasi untuk menampilkan peta.",
|
||||||
},
|
},
|
||||||
associatedDomains: ["applinks:cld-dkr-staging-hipmi.wibudev.com"],
|
associatedDomains: ["applinks:cld-dkr-staging-hipmi.wibudev.com"],
|
||||||
buildNumber: "15",
|
buildNumber: "19",
|
||||||
},
|
},
|
||||||
|
|
||||||
android: {
|
android: {
|
||||||
@@ -32,7 +32,7 @@ export default {
|
|||||||
},
|
},
|
||||||
edgeToEdgeEnabled: true,
|
edgeToEdgeEnabled: true,
|
||||||
package: "com.bip.hipmimobileapp",
|
package: "com.bip.hipmimobileapp",
|
||||||
versionCode: 3,
|
versionCode: 4,
|
||||||
// softwareKeyboardLayoutMode: 'resize', // option: untuk mengatur keyboard pada room chst collaboration
|
// softwareKeyboardLayoutMode: 'resize', // option: untuk mengatur keyboard pada room chst collaboration
|
||||||
intentFilters: [
|
intentFilters: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { BackButton } from "@/components";
|
import { BackButton } from "@/components";
|
||||||
|
import { IconPlus } from "@/components/_Icon";
|
||||||
|
import { IconDot } from "@/components/_Icon/IconComponent";
|
||||||
import LeftButtonCustom from "@/components/Button/BackButton";
|
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
@@ -51,24 +53,35 @@ export default function UserLayout() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{/* ========== Notification Section ========= */}
|
{/* ========== Notification Section ========= */}
|
||||||
<Stack.Screen
|
|
||||||
|
{/* DIPINDAH DI FILE NOTIFICATION USER */}
|
||||||
|
{/* <Stack.Screen
|
||||||
name="notifications/index"
|
name="notifications/index"
|
||||||
options={{
|
options={{
|
||||||
title: "Notifikasi",
|
title: "Notifikasi",
|
||||||
headerLeft: () => <BackButton />,
|
headerLeft: () => <BackButton />,
|
||||||
|
// headerRight: () => (
|
||||||
|
// <IconPlus
|
||||||
|
// color={MainColor.yellow}
|
||||||
|
// onPress={() => router.push("/test-notifications")}
|
||||||
|
// />
|
||||||
|
// ),
|
||||||
}}
|
}}
|
||||||
/>
|
/> */}
|
||||||
|
|
||||||
{/* ========== Event Section ========= */}
|
{/* ========== Event Section ========= */}
|
||||||
|
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="event/(tabs)"
|
name="event/(tabs)"
|
||||||
options={{
|
options={{
|
||||||
title: "Event",
|
title: "Event",
|
||||||
headerLeft: () => (
|
// NOTE: DIPINDAH DI FILE /Event/(Tabs)/_layout.tsx
|
||||||
<LeftButtonCustom path="/(application)/(user)/home" />
|
// headerLeft: () => (
|
||||||
),
|
// <LeftButtonCustom path="/(application)/(user)/home" />
|
||||||
|
// ),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="event/create"
|
name="event/create"
|
||||||
options={{
|
options={{
|
||||||
@@ -511,7 +524,8 @@ export default function UserLayout() {
|
|||||||
name="job/(tabs)"
|
name="job/(tabs)"
|
||||||
options={{
|
options={{
|
||||||
title: "Job Vacancy",
|
title: "Job Vacancy",
|
||||||
headerLeft: () => <BackButton path="/home" />,
|
// headerLeft: () => <BackButton path="/home" />,
|
||||||
|
// NOTE: headerLeft di pindahkan ke Tabs Layout
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
@@ -602,6 +616,20 @@ export default function UserLayout() {
|
|||||||
headerLeft: () => <BackButton />,
|
headerLeft: () => <BackButton />,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="forum/[id]/preview-report-posting"
|
||||||
|
options={{
|
||||||
|
title: "Laporan Postingan",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="forum/[id]/preview-report-comment"
|
||||||
|
options={{
|
||||||
|
title: "Laporan Komentar",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* ========== Maps Section ========= */}
|
{/* ========== Maps Section ========= */}
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import Donation_ComponentBoxDetailData from "@/screens/Donation/ComponentBoxDeta
|
|||||||
import Donation_ComponentStoryFunrising from "@/screens/Donation/ComponentStoryFunrising";
|
import Donation_ComponentStoryFunrising from "@/screens/Donation/ComponentStoryFunrising";
|
||||||
import Donation_ProgressSection from "@/screens/Donation/ProgressSection";
|
import Donation_ProgressSection from "@/screens/Donation/ProgressSection";
|
||||||
import { apiDonationGetOne } from "@/service/api-client/api-donation";
|
import { apiDonationGetOne } from "@/service/api-client/api-donation";
|
||||||
|
import { countDownAndCondition } from "@/utils/countDownAndCondition";
|
||||||
import { FontAwesome6 } from "@expo/vector-icons";
|
import { FontAwesome6 } from "@expo/vector-icons";
|
||||||
import {
|
import {
|
||||||
router,
|
router,
|
||||||
@@ -24,7 +25,7 @@ import {
|
|||||||
useLocalSearchParams,
|
useLocalSearchParams,
|
||||||
} from "expo-router";
|
} from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
export default function DonasiDetailStatus() {
|
export default function DonasiDetailStatus() {
|
||||||
const { id, status } = useLocalSearchParams();
|
const { id, status } = useLocalSearchParams();
|
||||||
@@ -58,6 +59,27 @@ export default function DonasiDetailStatus() {
|
|||||||
setOpenDrawer(false);
|
setOpenDrawer(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [value, setValue] = useState({
|
||||||
|
sisa: 0,
|
||||||
|
reminder: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
updateCountDown();
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
const updateCountDown = () => {
|
||||||
|
const countDown = countDownAndCondition({
|
||||||
|
duration: data?.DonasiMaster_Durasi?.name,
|
||||||
|
publishTime: data?.publishTime,
|
||||||
|
});
|
||||||
|
|
||||||
|
setValue({
|
||||||
|
sisa: countDown.durationDay,
|
||||||
|
reminder: countDown.reminder,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
@@ -74,10 +96,15 @@ export default function DonasiDetailStatus() {
|
|||||||
/>
|
/>
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
<Donation_ComponentBoxDetailData
|
<Donation_ComponentBoxDetailData
|
||||||
|
sisaHari={value.sisa}
|
||||||
|
reminder={value.reminder}
|
||||||
data={data}
|
data={data}
|
||||||
bottomSection={
|
bottomSection={
|
||||||
status === "publish" && (
|
status === "publish" && (
|
||||||
<Donation_ProgressSection id={id as string} />
|
<Donation_ProgressSection
|
||||||
|
id={id as string}
|
||||||
|
progres={Number(data?.progres) || 0}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,10 +4,34 @@ import {
|
|||||||
IconHome,
|
IconHome,
|
||||||
IconStatus,
|
IconStatus,
|
||||||
} from "@/components/_Icon";
|
} from "@/components/_Icon";
|
||||||
|
import BackButtonFromNotification from "@/components/Button/BackButtonFromNotification";
|
||||||
import { TabsStyles } from "@/styles/tabs-styles";
|
import { TabsStyles } from "@/styles/tabs-styles";
|
||||||
import { Tabs } from "expo-router";
|
import { router, Tabs, useLocalSearchParams, useNavigation } from "expo-router";
|
||||||
|
import { useLayoutEffect } from "react";
|
||||||
|
|
||||||
export default function EventTabsLayout() {
|
export default function EventTabsLayout() {
|
||||||
|
const navigation = useNavigation();
|
||||||
|
|
||||||
|
const { from, category } = useLocalSearchParams<{
|
||||||
|
from?: string;
|
||||||
|
category?: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
console.log("from", from);
|
||||||
|
console.log("category", category);
|
||||||
|
|
||||||
|
// Atur header secara dinamis
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
navigation.setOptions({
|
||||||
|
headerLeft: () => (
|
||||||
|
<BackButtonFromNotification
|
||||||
|
from={from as string}
|
||||||
|
category={category as string}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}, [from, router, navigation]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs screenOptions={TabsStyles}>
|
<Tabs screenOptions={TabsStyles}>
|
||||||
<Tabs.Screen
|
<Tabs.Screen
|
||||||
|
|||||||
@@ -11,15 +11,17 @@ import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
|||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import { dummyMasterStatus } from "@/lib/dummy-data/_master/status";
|
import { dummyMasterStatus } from "@/lib/dummy-data/_master/status";
|
||||||
import { apiEventGetByStatus } from "@/service/api-client/api-event";
|
import { apiEventGetByStatus } from "@/service/api-client/api-event";
|
||||||
import { useFocusEffect } from "expo-router";
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export default function EventStatus() {
|
export default function EventStatus() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
const { status } = useLocalSearchParams<{ status?: string }>();
|
||||||
|
|
||||||
const id = user?.id || "";
|
const id = user?.id || "";
|
||||||
const [activeCategory, setActiveCategory] = useState<string | null>(
|
const [activeCategory, setActiveCategory] = useState<string | null>(
|
||||||
"publish"
|
status || "publish"
|
||||||
);
|
);
|
||||||
const [listData, setListData] = useState([]);
|
const [listData, setListData] = useState([]);
|
||||||
const [loadingGetData, setLoadingGetData] = useState(false);
|
const [loadingGetData, setLoadingGetData] = useState(false);
|
||||||
@@ -73,7 +75,7 @@ export default function EventStatus() {
|
|||||||
listData.map((item: any, i) => (
|
listData.map((item: any, i) => (
|
||||||
<BoxWithHeaderSection
|
<BoxWithHeaderSection
|
||||||
key={i}
|
key={i}
|
||||||
href={`/event/${item.id }/${activeCategory}/detail-event`}
|
href={`/event/${item.id}/${activeCategory}/detail-event`}
|
||||||
>
|
>
|
||||||
<StackCustom gap={"xs"}>
|
<StackCustom gap={"xs"}>
|
||||||
<Grid>
|
<Grid>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export default function EventDetailHistory() {
|
|||||||
<DrawerCustom
|
<DrawerCustom
|
||||||
isVisible={openDrawer}
|
isVisible={openDrawer}
|
||||||
closeDrawer={() => setOpenDrawer(false)}
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
height={250}
|
height={"auto"}
|
||||||
>
|
>
|
||||||
<MenuDrawerDynamicGrid
|
<MenuDrawerDynamicGrid
|
||||||
data={menuDrawerPublishEvent({ id: id as string })}
|
data={menuDrawerPublishEvent({ id: id as string })}
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
AlertDefaultSystem,
|
AlertDefaultSystem,
|
||||||
|
BackButton,
|
||||||
ButtonCustom,
|
ButtonCustom,
|
||||||
DotButton,
|
DotButton,
|
||||||
DrawerCustom,
|
DrawerCustom,
|
||||||
LoaderCustom,
|
|
||||||
MenuDrawerDynamicGrid,
|
MenuDrawerDynamicGrid,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
|
import CustomSkeleton from "@/components/_ShareComponent/SkeletonCustom";
|
||||||
import LeftButtonCustom from "@/components/Button/BackButton";
|
import LeftButtonCustom from "@/components/Button/BackButton";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import Event_BoxDetailPublishSection from "@/screens/Event/BoxDetailPublishSection";
|
import Event_BoxDetailPublishSection from "@/screens/Event/BoxDetailPublishSection";
|
||||||
@@ -18,23 +19,26 @@ import {
|
|||||||
apiEventGetOne,
|
apiEventGetOne,
|
||||||
apiEventJoin,
|
apiEventJoin,
|
||||||
} from "@/service/api-client/api-event";
|
} from "@/service/api-client/api-event";
|
||||||
|
import dayjs from "dayjs";
|
||||||
import {
|
import {
|
||||||
|
Redirect,
|
||||||
router,
|
router,
|
||||||
Stack,
|
Stack,
|
||||||
useFocusEffect,
|
useFocusEffect,
|
||||||
useLocalSearchParams,
|
useLocalSearchParams,
|
||||||
} from "expo-router";
|
} from "expo-router";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function EventDetailPublish() {
|
export default function EventDetailPublish() {
|
||||||
const { id } = useLocalSearchParams();
|
const now = new Date().toISOString();
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
const [openDrawer, setOpenDrawer] = useState(false);
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
const [isLoadingData, setIsLoadingData] = useState(false);
|
const [isLoadingData, setIsLoadingData] = useState(false);
|
||||||
const [isLoadingJoin, setIsLoadingJoin] = useState(false);
|
const [isLoadingJoin, setIsLoadingJoin] = useState(false);
|
||||||
|
|
||||||
const [data, setData] = useState();
|
const [data, setData] = useState<any>();
|
||||||
const [isParticipant, setIsParticipant] = useState<boolean | null>(null);
|
const [isParticipant, setIsParticipant] = useState<boolean | null>(null);
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
@@ -55,8 +59,6 @@ export default function EventDetailPublish() {
|
|||||||
userId: user?.id as string,
|
userId: user?.id as string,
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("[RES CHECK PARTICIPANTS]", responseCheckParticipants);
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
responseCheckParticipants.success &&
|
responseCheckParticipants.success &&
|
||||||
responseCheckParticipants.data
|
responseCheckParticipants.data
|
||||||
@@ -108,7 +110,24 @@ export default function EventDetailPublish() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const footerButton = () => {
|
const isEventFinished =
|
||||||
|
id && data?.tanggalSelesai && dayjs(data.tanggalSelesai).isBefore(now);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isEventFinished) {
|
||||||
|
router.replace(`/(application)/(user)/event/${id}/history`);
|
||||||
|
}
|
||||||
|
}, [isEventFinished, id]);
|
||||||
|
|
||||||
|
if (isEventFinished) {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<CustomSkeleton />
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const FooterButton = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
@@ -138,17 +157,17 @@ export default function EventDetailPublish() {
|
|||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
options={{
|
options={{
|
||||||
title: `Event Publish`,
|
title: `Event Publish`,
|
||||||
headerLeft: () => <LeftButtonCustom />,
|
headerLeft: () => <BackButton onPress={() => router.back()} />,
|
||||||
headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
{isLoadingData ? (
|
{isLoadingData ? (
|
||||||
<LoaderCustom />
|
<CustomSkeleton height={400} />
|
||||||
) : (
|
) : (
|
||||||
<Event_BoxDetailPublishSection
|
<Event_BoxDetailPublishSection
|
||||||
data={data}
|
data={data}
|
||||||
footerButton={footerButton()}
|
footerButton={FooterButton()}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { apiEventCreate } from "@/service/api-client/api-event";
|
|||||||
import { apiMasterEventType } from "@/service/api-client/api-master";
|
import { apiMasterEventType } from "@/service/api-client/api-master";
|
||||||
import { DateTimePickerEvent } from "@react-native-community/datetimepicker";
|
import { DateTimePickerEvent } from "@react-native-community/datetimepicker";
|
||||||
import { router } from "expo-router";
|
import { router } from "expo-router";
|
||||||
import React, { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
interface EventCreateProps {
|
interface EventCreateProps {
|
||||||
@@ -78,23 +78,6 @@ export default function EventCreate() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (selectedDate) {
|
|
||||||
// console.log("Tanggal yang dipilih:", selectedDate);
|
|
||||||
// console.log(`ISO Format ${Platform.OS}:`, selectedDate.toString());
|
|
||||||
|
|
||||||
// // Kirim ke API atau proses lanjutan
|
|
||||||
// } else {
|
|
||||||
// console.log("Tanggal belum dipilih");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (selectedEndDate) {
|
|
||||||
// console.log("Tanggal yang dipilih:", selectedEndDate);
|
|
||||||
// console.log(`ISO Format ${Platform.OS}:`, selectedEndDate.toString());
|
|
||||||
// // Kirim ke API atau proses lanjutan
|
|
||||||
// } else {
|
|
||||||
// console.log("Tanggal berakhir belum dipilih");
|
|
||||||
// }
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
@@ -110,7 +93,7 @@ export default function EventCreate() {
|
|||||||
const response = await apiEventCreate(newData);
|
const response = await apiEventCreate(newData);
|
||||||
console.log("Response", JSON.stringify(response, null, 2));
|
console.log("Response", JSON.stringify(response, null, 2));
|
||||||
|
|
||||||
router.replace("/event/status");
|
router.replace("/event/status?status=review");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -19,34 +19,20 @@ import {
|
|||||||
apiForumGetOne,
|
apiForumGetOne,
|
||||||
apiForumUpdateStatus,
|
apiForumUpdateStatus,
|
||||||
} from "@/service/api-client/api-forum";
|
} from "@/service/api-client/api-forum";
|
||||||
|
import { TypeForum_CommentProps } from "@/types/type-forum";
|
||||||
import { isBadContent } from "@/utils/badWordsIndonesia";
|
import { isBadContent } from "@/utils/badWordsIndonesia";
|
||||||
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { Alert } from "react-native";
|
|
||||||
|
|
||||||
interface CommentProps {
|
|
||||||
id: string;
|
|
||||||
isActive: boolean;
|
|
||||||
komentar: string;
|
|
||||||
createdAt: Date;
|
|
||||||
authorId: string;
|
|
||||||
Author: {
|
|
||||||
id: string;
|
|
||||||
username: string;
|
|
||||||
Profile: {
|
|
||||||
id: string;
|
|
||||||
imageId: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function ForumDetail() {
|
export default function ForumDetail() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const [openDrawer, setOpenDrawer] = useState(false);
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
const [data, setData] = useState<any | null>(null);
|
const [data, setData] = useState<any | null>(null);
|
||||||
const [listComment, setListComment] = useState<CommentProps[] | null>(null);
|
const [listComment, setListComment] = useState<TypeForum_CommentProps[] | null>(null);
|
||||||
const [isLoadingComment, setLoadingComment] = useState(false);
|
const [isLoadingComment, setLoadingComment] = useState(false);
|
||||||
|
|
||||||
// Status
|
// Status
|
||||||
@@ -122,6 +108,7 @@ export default function ForumDetail() {
|
|||||||
comment: text,
|
comment: text,
|
||||||
authorId: user?.id,
|
authorId: user?.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setLoadingComment(true);
|
setLoadingComment(true);
|
||||||
const response = await apiForumCreateComment({
|
const response = await apiForumCreateComment({
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
} from "@/components";
|
} 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 { apiForumCreateReportCommentar } from "@/service/api-client/api-master";
|
import { apiForumCreateReportCommentar } from "@/service/api-client/api-forum";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
} from "@/components";
|
} 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 { apiForumCreateReportPosting } from "@/service/api-client/api-master";
|
import { apiForumCreateReportPosting } from "@/service/api-client/api-forum";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
NewWrapper,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
} from "@/components";
|
||||||
|
import ListSkeletonComponent from "@/components/_ShareComponent/ListSkeletonComponent";
|
||||||
|
import NoDataText from "@/components/_ShareComponent/NoDataText";
|
||||||
|
import CustomSkeleton from "@/components/_ShareComponent/SkeletonCustom";
|
||||||
|
import { apiForumGetReportComment } from "@/service/api-client/api-forum";
|
||||||
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
|
export default function ForumPreviewReportComment() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [data, setData] = useState<any | null>(null);
|
||||||
|
const [listData, setListData] = useState<any | null>(null);
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
// Status
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData(id as string);
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async (id: string) => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const response = await apiForumGetReportComment({ id });
|
||||||
|
setData(response.data);
|
||||||
|
setListData(response?.data?.Forum_ReportKomentar);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<NewWrapper>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom color="red" bold>
|
||||||
|
Komentar anda telah melanggar aturan forum ! Admin mengambil
|
||||||
|
tindakan untuk menghapus komentar anda!
|
||||||
|
</TextCustom>
|
||||||
|
{loading ? (
|
||||||
|
<CustomSkeleton height={100} />
|
||||||
|
) : (
|
||||||
|
<BaseBox>
|
||||||
|
<TextCustom>"{data?.komentar ? data?.komentar : "-"}"</TextCustom>
|
||||||
|
</BaseBox>
|
||||||
|
)}
|
||||||
|
</StackCustom>
|
||||||
|
|
||||||
|
<Spacing height={10} />
|
||||||
|
<TextCustom bold>Beberapa laporan yang telah diterima</TextCustom>
|
||||||
|
<Spacing height={10} />
|
||||||
|
|
||||||
|
{loading ? (
|
||||||
|
<ListSkeletonComponent />
|
||||||
|
) : _.isEmpty(listData) ? (
|
||||||
|
<NoDataText />
|
||||||
|
) : (
|
||||||
|
listData?.map((e: any, index: number) => (
|
||||||
|
<BaseBox key={index}>
|
||||||
|
{e?.deskripsi ? (
|
||||||
|
<StackCustom gap={"sm"}>
|
||||||
|
<TextCustom bold>Laporan Lainnya</TextCustom>
|
||||||
|
<TextCustom>{e?.deskripsi}</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
) : (
|
||||||
|
<StackCustom gap={"sm"}>
|
||||||
|
<TextCustom bold>
|
||||||
|
{e?.ForumMaster_KategoriReport?.title}
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom>
|
||||||
|
{e?.ForumMaster_KategoriReport?.deskripsi}
|
||||||
|
</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
)}
|
||||||
|
</BaseBox>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</NewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
import {
|
||||||
|
BaseBox,
|
||||||
|
NewWrapper,
|
||||||
|
Spacing,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
} from "@/components";
|
||||||
|
import ListSkeletonComponent from "@/components/_ShareComponent/ListSkeletonComponent";
|
||||||
|
import NoDataText from "@/components/_ShareComponent/NoDataText";
|
||||||
|
import CustomSkeleton from "@/components/_ShareComponent/SkeletonCustom";
|
||||||
|
import { apiForumGetReportPosting } from "@/service/api-client/api-forum";
|
||||||
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
|
export default function ForumPreviewReportPosting() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [data, setData] = useState<any | null>(null);
|
||||||
|
const [listData, setListData] = useState<any | null>(null);
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
// Status
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData(id as string);
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async (id: string) => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const response = await apiForumGetReportPosting({ id });
|
||||||
|
setData(response.data);
|
||||||
|
setListData(response?.data?.Forum_ReportPosting);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<NewWrapper>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom color="red" bold>
|
||||||
|
Postingan anda telah melanggar aturan forum ! Admin mengambil
|
||||||
|
tindakan untuk menghapus komentar anda!
|
||||||
|
</TextCustom>
|
||||||
|
{loading ? (
|
||||||
|
<CustomSkeleton height={100} />
|
||||||
|
) : (
|
||||||
|
<BaseBox>
|
||||||
|
<TextCustom>"{data?.diskusi ? data?.diskusi : "-"}"</TextCustom>
|
||||||
|
</BaseBox>
|
||||||
|
)}
|
||||||
|
</StackCustom>
|
||||||
|
|
||||||
|
<Spacing height={10} />
|
||||||
|
<TextCustom bold>Beberapa laporan yang telah diterima</TextCustom>
|
||||||
|
<Spacing height={10} />
|
||||||
|
|
||||||
|
{loading ? (
|
||||||
|
<ListSkeletonComponent />
|
||||||
|
) : _.isEmpty(listData) ? (
|
||||||
|
<NoDataText />
|
||||||
|
) : (
|
||||||
|
listData?.map((e: any) => (
|
||||||
|
<BaseBox key={e?.id}>
|
||||||
|
{e?.deskripsi ? (
|
||||||
|
<StackCustom gap={"sm"}>
|
||||||
|
<TextCustom bold>Laporan Lainnya</TextCustom>
|
||||||
|
<TextCustom>{e?.deskripsi}</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
) : (
|
||||||
|
<StackCustom gap={"sm"}>
|
||||||
|
<TextCustom bold>
|
||||||
|
{e?.ForumMaster_KategoriReport?.title}
|
||||||
|
</TextCustom>
|
||||||
|
<TextCustom>
|
||||||
|
{e?.ForumMaster_KategoriReport?.deskripsi}
|
||||||
|
</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
)}
|
||||||
|
</BaseBox>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</NewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -8,7 +8,8 @@ import {
|
|||||||
import { AccentColor, MainColor } from "@/constants/color-palet";
|
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import Forum_ReportListSection from "@/screens/Forum/ReportListSection";
|
import Forum_ReportListSection from "@/screens/Forum/ReportListSection";
|
||||||
import { apiForumCreateReportCommentar, apiMasterForumReportList } from "@/service/api-client/api-master";
|
import { apiForumCreateReportCommentar } from "@/service/api-client/api-forum";
|
||||||
|
import { apiMasterForumReportList } from "@/service/api-client/api-master";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import {
|
|||||||
import { AccentColor, MainColor } from "@/constants/color-palet";
|
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import Forum_ReportListSection from "@/screens/Forum/ReportListSection";
|
import Forum_ReportListSection from "@/screens/Forum/ReportListSection";
|
||||||
|
import { apiForumCreateReportPosting } from "@/service/api-client/api-forum";
|
||||||
import {
|
import {
|
||||||
apiForumCreateReportPosting,
|
|
||||||
apiMasterForumReportList,
|
apiMasterForumReportList,
|
||||||
} from "@/service/api-client/api-master";
|
} from "@/service/api-client/api-master";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
|||||||
@@ -2,15 +2,14 @@ import {
|
|||||||
BoxButtonOnFooter,
|
BoxButtonOnFooter,
|
||||||
ButtonCustom,
|
ButtonCustom,
|
||||||
TextAreaCustom,
|
TextAreaCustom,
|
||||||
ViewWrapper
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AlertWarning from "@/components/Alert/AlertWarning";
|
import AlertWarning from "@/components/Alert/AlertWarning";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import { apiForumCreate } from "@/service/api-client/api-forum";
|
import { apiForumCreate } from "@/service/api-client/api-forum";
|
||||||
import { isBadContent } from "@/utils/badWordsIndonesia";
|
import { censorText, isBadContent } from "@/utils/badWordsIndonesia";
|
||||||
import { router } from "expo-router";
|
import { router } from "expo-router";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Alert } from "react-native";
|
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function ForumCreate() {
|
export default function ForumCreate() {
|
||||||
@@ -19,16 +18,22 @@ export default function ForumCreate() {
|
|||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
const handlerSubmit = async () => {
|
const handlerSubmit = async () => {
|
||||||
|
if (text.trim() === "") {
|
||||||
if (isBadContent(text)) {
|
AlertWarning({
|
||||||
AlertWarning({})
|
title: "Lengkapi Data",
|
||||||
|
description: "Postingan tidak boleh kosong",
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bisa di sensor atau return dan tidak bisa di post
|
||||||
|
const cencorContent = censorText(text)
|
||||||
|
|
||||||
const newData = {
|
const newData = {
|
||||||
diskusi: text,
|
diskusi: cencorContent,
|
||||||
authorId: user?.id,
|
authorId: user?.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const response = await apiForumCreate({ data: newData });
|
const response = await apiForumCreate({ data: newData });
|
||||||
@@ -50,6 +55,7 @@ export default function ForumCreate() {
|
|||||||
const buttonFooter = (
|
const buttonFooter = (
|
||||||
<BoxButtonOnFooter>
|
<BoxButtonOnFooter>
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
|
disabled={!text.trim() || isLoading}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
handlerSubmit();
|
handlerSubmit();
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
import { StackCustom, ViewWrapper } from "@/components";
|
import { 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";
|
||||||
@@ -12,21 +14,21 @@ import { apiUser } from "@/service/api-client/api-user";
|
|||||||
import { apiVersion } from "@/service/api-config";
|
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, useState } from "react";
|
||||||
import { RefreshControl } from "react-native";
|
import { RefreshControl } 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));
|
const { syncUnreadCount } = useNotificationStore();
|
||||||
|
|
||||||
// ‼️ 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();
|
||||||
checkVersion();
|
checkVersion();
|
||||||
userData(token as string);
|
userData(token as string);
|
||||||
|
syncUnreadCount();
|
||||||
}, [user?.id, token])
|
}, [user?.id, token])
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -52,10 +54,10 @@ export default function Application() {
|
|||||||
setRefreshing(false);
|
setRefreshing(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (user && user?.termsOfServiceAccepted === false) {
|
// if (user && user?.termsOfServiceAccepted === false) {
|
||||||
console.log("User is not accept term service");
|
// console.log("User is not accept term service");
|
||||||
return <Redirect href={`/terms-agreement`} />;
|
// return <Redirect href={`/terms-agreement`} />;
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (data && data?.active === false) {
|
if (data && data?.active === false) {
|
||||||
console.log("User is not active");
|
console.log("User is not active");
|
||||||
@@ -82,17 +84,7 @@ export default function Application() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
headerRight: () => (
|
headerRight: () => <HeaderBell />,
|
||||||
<Ionicons
|
|
||||||
disabled={true}
|
|
||||||
name="notifications"
|
|
||||||
size={20}
|
|
||||||
color={MainColor.placeholder}
|
|
||||||
onPress={() => {
|
|
||||||
router.push("/notifications");
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ViewWrapper
|
<ViewWrapper
|
||||||
@@ -109,6 +101,10 @@ export default function Application() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
|
{/* <ButtonCustom onPress={() => router.push("./test-notifications")}>
|
||||||
|
Test Notif
|
||||||
|
</ButtonCustom> */}
|
||||||
|
|
||||||
<Home_ImageSection />
|
<Home_ImageSection />
|
||||||
|
|
||||||
<Home_FeatureSection />
|
<Home_FeatureSection />
|
||||||
|
|||||||
@@ -1,9 +1,33 @@
|
|||||||
|
import BackButtonFromNotification from "@/components/Button/BackButtonFromNotification";
|
||||||
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
import { TabsStyles } from "@/styles/tabs-styles";
|
import { TabsStyles } from "@/styles/tabs-styles";
|
||||||
import { Feather, FontAwesome6, Ionicons } from "@expo/vector-icons";
|
import { Feather, FontAwesome6, Ionicons } from "@expo/vector-icons";
|
||||||
import { Tabs } from "expo-router";
|
import { router, Tabs, useLocalSearchParams, useNavigation } from "expo-router";
|
||||||
|
import { useLayoutEffect } from "react";
|
||||||
|
|
||||||
export default function InvestmentTabsLayout() {
|
export default function InvestmentTabsLayout() {
|
||||||
|
// const navigation = useNavigation();
|
||||||
|
|
||||||
|
// const { from, category } = useLocalSearchParams<{
|
||||||
|
// from?: string;
|
||||||
|
// category?: string;
|
||||||
|
// }>();
|
||||||
|
|
||||||
|
// console.log("from", from);
|
||||||
|
// console.log("category", category);
|
||||||
|
|
||||||
|
// // Atur header secara dinamis
|
||||||
|
// useLayoutEffect(() => {
|
||||||
|
// navigation.setOptions({
|
||||||
|
// headerLeft: () => (
|
||||||
|
// <BackButtonFromNotification
|
||||||
|
// from={from as string}
|
||||||
|
// category={category as string}
|
||||||
|
// />
|
||||||
|
// ),
|
||||||
|
// });
|
||||||
|
// }, [from, router, navigation]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs screenOptions={TabsStyles}>
|
<Tabs screenOptions={TabsStyles}>
|
||||||
<Tabs.Screen
|
<Tabs.Screen
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ import {
|
|||||||
} from "@/components";
|
} from "@/components";
|
||||||
import NoDataText from "@/components/_ShareComponent/NoDataText";
|
import NoDataText from "@/components/_ShareComponent/NoDataText";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import {
|
import { apiInvestmentGetAll } from "@/service/api-client/api-investment";
|
||||||
apiInvestmentGetAll
|
|
||||||
} from "@/service/api-client/api-investment";
|
|
||||||
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
import { router, useFocusEffect } from "expo-router";
|
import { router, useFocusEffect } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
@@ -63,37 +61,20 @@ export default function InvestmentMyHolding() {
|
|||||||
router.push(`/investment/${item?.id}/(my-holding)/${item?.id}`)
|
router.push(`/investment/${item?.id}/(my-holding)/${item?.id}`)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Grid>
|
<StackCustom>
|
||||||
<Grid.Col span={6}>
|
<TextCustom truncate={2}>{item?.title}</TextCustom>
|
||||||
<StackCustom gap={"xs"}>
|
<TextCustom>
|
||||||
<TextCustom truncate={2}>{item?.title}</TextCustom>
|
Rp. {formatCurrencyDisplay(item?.nominal)}
|
||||||
|
</TextCustom>
|
||||||
<Spacing height={5} />
|
<TextCustom>{item?.lembarTerbeli} Lembar</TextCustom>
|
||||||
<TextCustom size="small">
|
<ProgressCustom
|
||||||
Rp. {formatCurrencyDisplay(item?.nominal)}
|
label={`${item.progress}%`}
|
||||||
</TextCustom>
|
value={Number(item.progress)}
|
||||||
<TextCustom size="small">
|
size="lg"
|
||||||
{item?.lembarTerbeli} Lembar
|
animated
|
||||||
</TextCustom>
|
color="primary"
|
||||||
</StackCustom>
|
/>
|
||||||
</Grid.Col>
|
</StackCustom>
|
||||||
<Grid.Col span={1}>
|
|
||||||
<View />
|
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col
|
|
||||||
span={5}
|
|
||||||
style={{
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ProgressCustom
|
|
||||||
value={item?.progress}
|
|
||||||
label={`${item?.progress}%`}
|
|
||||||
size="lg"
|
|
||||||
/>
|
|
||||||
</Grid.Col>
|
|
||||||
</Grid>
|
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -9,14 +9,16 @@ import { useAuth } from "@/hooks/use-auth";
|
|||||||
import { dummyMasterStatus } from "@/lib/dummy-data/_master/status";
|
import { dummyMasterStatus } from "@/lib/dummy-data/_master/status";
|
||||||
import Investment_StatusBox from "@/screens/Invesment/StatusBox";
|
import Investment_StatusBox from "@/screens/Invesment/StatusBox";
|
||||||
import { apiInvestmentGetByStatus } from "@/service/api-client/api-investment";
|
import { apiInvestmentGetByStatus } from "@/service/api-client/api-investment";
|
||||||
import { useFocusEffect } from "expo-router";
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export default function InvestmentPortofolio() {
|
export default function InvestmentPortofolio() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
const { status } = useLocalSearchParams<{ status?: string }>();
|
||||||
|
|
||||||
const [activeCategory, setActiveCategory] = useState<string | null>(
|
const [activeCategory, setActiveCategory] = useState<string | null>(
|
||||||
"publish"
|
status || "publish"
|
||||||
);
|
);
|
||||||
|
|
||||||
const [listData, setListData] = useState<any[]>([]);
|
const [listData, setListData] = useState<any[]>([]);
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import Toast from "react-native-toast-message";
|
|||||||
|
|
||||||
export default function InvestmentInvoice() {
|
export default function InvestmentInvoice() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
console.log("[ID]", id);
|
|
||||||
const [data, setData] = useState<any>({});
|
const [data, setData] = useState<any>({});
|
||||||
const [image, setImage] = useState<IFileData>({
|
const [image, setImage] = useState<IFileData>({
|
||||||
name: "",
|
name: "",
|
||||||
@@ -49,7 +48,6 @@ export default function InvestmentInvoice() {
|
|||||||
category: "invoice",
|
category: "invoice",
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("[RES INVOICE]", JSON.stringify(response.data, null, 2));
|
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
@@ -64,8 +62,6 @@ export default function InvestmentInvoice() {
|
|||||||
imageUri: image?.uri,
|
imageUri: image?.uri,
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("[RESPONSE UPLOAD IMAGE]", responseUploadImage);
|
|
||||||
|
|
||||||
if (!responseUploadImage?.data?.id) {
|
if (!responseUploadImage?.data?.id) {
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: "error",
|
type: "error",
|
||||||
@@ -83,10 +79,6 @@ export default function InvestmentInvoice() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
console.log(
|
|
||||||
"[RESPONSE UPDATE]",
|
|
||||||
JSON.stringify(response.data, null, 2)
|
|
||||||
);
|
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: "success",
|
type: "success",
|
||||||
text1: "Berhasil mengunggah bukti transfer",
|
text1: "Berhasil mengunggah bukti transfer",
|
||||||
@@ -210,7 +202,6 @@ export default function InvestmentInvoice() {
|
|||||||
pickFile({
|
pickFile({
|
||||||
allowedType: "image",
|
allowedType: "image",
|
||||||
setImageUri(file: any) {
|
setImageUri(file: any) {
|
||||||
console.log("[IMAGE]", file);
|
|
||||||
setImage(file);
|
setImage(file);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -224,7 +215,7 @@ export default function InvestmentInvoice() {
|
|||||||
|
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
disabled={!image}
|
disabled={!image || isLoading}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
handlerSubmitUpdate();
|
handlerSubmitUpdate();
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import Investment_ButtonInvestasiSection from "@/screens/Invesment/ButtonInvesta
|
|||||||
import Invesment_ComponentBoxOnBottomDetail from "@/screens/Invesment/ComponentBoxOnBottomDetail";
|
import Invesment_ComponentBoxOnBottomDetail from "@/screens/Invesment/ComponentBoxOnBottomDetail";
|
||||||
import Invesment_DetailDataPublishSection from "@/screens/Invesment/DetailDataPublishSection";
|
import Invesment_DetailDataPublishSection from "@/screens/Invesment/DetailDataPublishSection";
|
||||||
import { apiInvestmentGetOne } from "@/service/api-client/api-investment";
|
import { apiInvestmentGetOne } from "@/service/api-client/api-investment";
|
||||||
|
import { countDownAndCondition } from "@/utils/countDownAndCondition";
|
||||||
import { AntDesign, MaterialIcons } from "@expo/vector-icons";
|
import { AntDesign, MaterialIcons } from "@expo/vector-icons";
|
||||||
import {
|
import {
|
||||||
router,
|
router,
|
||||||
@@ -23,7 +24,7 @@ import {
|
|||||||
useLocalSearchParams,
|
useLocalSearchParams,
|
||||||
} from "expo-router";
|
} from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
export default function InvestmentDetailStatus() {
|
export default function InvestmentDetailStatus() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
@@ -63,6 +64,29 @@ export default function InvestmentDetailStatus() {
|
|||||||
setOpenDrawerPublish(false);
|
setOpenDrawerPublish(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [value, setValue] = useState({
|
||||||
|
sisa: 0,
|
||||||
|
reminder: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
updateCountDown();
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
console.log("[DATA DETAIL]", JSON.stringify(data, null, 2));
|
||||||
|
|
||||||
|
const updateCountDown = () => {
|
||||||
|
const countDown = countDownAndCondition({
|
||||||
|
duration: data?.MasterPencarianInvestor.name,
|
||||||
|
publishTime: data?.countDown,
|
||||||
|
});
|
||||||
|
|
||||||
|
setValue({
|
||||||
|
sisa: countDown.durationDay,
|
||||||
|
reminder: countDown.reminder,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const bottomSection = (
|
const bottomSection = (
|
||||||
<Invesment_ComponentBoxOnBottomDetail
|
<Invesment_ComponentBoxOnBottomDetail
|
||||||
id={data?.id}
|
id={data?.id}
|
||||||
@@ -72,7 +96,11 @@ export default function InvestmentDetailStatus() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const buttonSection = (
|
const buttonSection = (
|
||||||
<Investment_ButtonInvestasiSection id={id as string} isMine={user?.id === data?.author?.id} />
|
<Investment_ButtonInvestasiSection
|
||||||
|
id={id as string}
|
||||||
|
isMine={user?.id === data?.author?.id}
|
||||||
|
reminder={value.reminder}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -63,30 +63,28 @@ export default function InvestmentDetail() {
|
|||||||
setOpenDrawerPublish(false);
|
setOpenDrawerPublish(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const [value, setValue] = useState({
|
const [value, setValue] = useState({
|
||||||
sisa: 0,
|
sisa: 0,
|
||||||
reminder: false,
|
reminder: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
updateCountDown();
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
console.log("[DATA DETAIL]", JSON.stringify(data, null, 2));
|
||||||
|
|
||||||
|
const updateCountDown = () => {
|
||||||
|
const countDown = countDownAndCondition({
|
||||||
|
duration: data?.MasterPencarianInvestor.name,
|
||||||
|
publishTime: data?.countDown,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
setValue({
|
||||||
updateCountDown();
|
sisa: countDown.durationDay,
|
||||||
}, [data]);
|
reminder: countDown.reminder,
|
||||||
|
});
|
||||||
console.log("[DATA DETAIL]", JSON.stringify(data, null, 2));
|
};
|
||||||
|
|
||||||
const updateCountDown = () => {
|
|
||||||
const countDown = countDownAndCondition({
|
|
||||||
duration: data?.MasterPencarianInvestor.name,
|
|
||||||
publishTime: data?.countDown,
|
|
||||||
});
|
|
||||||
|
|
||||||
setValue({
|
|
||||||
sisa: countDown.durationDay,
|
|
||||||
reminder: countDown.reminder,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const bottomSection = (
|
const bottomSection = (
|
||||||
<Invesment_ComponentBoxOnBottomDetail
|
<Invesment_ComponentBoxOnBottomDetail
|
||||||
@@ -97,7 +95,11 @@ export default function InvestmentDetail() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const buttonSection = (
|
const buttonSection = (
|
||||||
<Investment_ButtonInvestasiSection id={id as string} isMine={user?.id === data?.author?.id} reminder={value.reminder} />
|
<Investment_ButtonInvestasiSection
|
||||||
|
id={id as string}
|
||||||
|
isMine={user?.id === data?.author?.id}
|
||||||
|
reminder={value.reminder}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ export default function InvestmentCreate() {
|
|||||||
text1: "Berhasil",
|
text1: "Berhasil",
|
||||||
text2: response.message,
|
text2: response.message,
|
||||||
});
|
});
|
||||||
router.replace("/investment/portofolio");
|
router.replace("/investment/portofolio?status=review");
|
||||||
} else {
|
} else {
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: "error",
|
type: "error",
|
||||||
@@ -224,7 +224,6 @@ export default function InvestmentCreate() {
|
|||||||
onPress={() => {
|
onPress={() => {
|
||||||
pickFile({
|
pickFile({
|
||||||
setPdfUri: ({ uri, name, size }) => {
|
setPdfUri: ({ uri, name, size }) => {
|
||||||
|
|
||||||
setPdf({ uri, name, size });
|
setPdf({ uri, name, size });
|
||||||
},
|
},
|
||||||
allowedType: "pdf",
|
allowedType: "pdf",
|
||||||
@@ -357,7 +356,11 @@ export default function InvestmentCreate() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<Spacing />
|
<Spacing />
|
||||||
<ButtonCustom isLoading={isLoading} onPress={() => handleSubmit()}>
|
<ButtonCustom
|
||||||
|
disabled={isLoading}
|
||||||
|
isLoading={isLoading}
|
||||||
|
onPress={() => handleSubmit()}
|
||||||
|
>
|
||||||
Simpan
|
Simpan
|
||||||
</ButtonCustom>
|
</ButtonCustom>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
|
|||||||
@@ -1,34 +1,61 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
import { BackButton } from "@/components";
|
||||||
import { IconHome, IconStatus } from "@/components/_Icon";
|
import { IconHome, IconStatus } from "@/components/_Icon";
|
||||||
|
import BackButtonFromNotification from "@/components/Button/BackButtonFromNotification";
|
||||||
import { TabsStyles } from "@/styles/tabs-styles";
|
import { TabsStyles } from "@/styles/tabs-styles";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import { Tabs } from "expo-router";
|
import {
|
||||||
|
router,
|
||||||
|
Tabs,
|
||||||
|
useLocalSearchParams,
|
||||||
|
useNavigation
|
||||||
|
} from "expo-router";
|
||||||
|
import { useLayoutEffect } from "react";
|
||||||
|
|
||||||
export default function JobTabsLayout() {
|
export default function JobTabsLayout() {
|
||||||
|
const navigation = useNavigation();
|
||||||
|
|
||||||
|
const { from, category } = useLocalSearchParams<{
|
||||||
|
from?: string;
|
||||||
|
category?: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// Atur header secara dinamis
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
navigation.setOptions({
|
||||||
|
headerLeft: () => (
|
||||||
|
<BackButtonFromNotification from={from as string} category={category as string} />
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}, [from, router, navigation]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs screenOptions={TabsStyles}>
|
<>
|
||||||
<Tabs.Screen
|
<Tabs screenOptions={TabsStyles}>
|
||||||
name="index"
|
<Tabs.Screen
|
||||||
options={{
|
name="index"
|
||||||
title: "Beranda",
|
options={{
|
||||||
tabBarIcon: ({ color }) => <IconHome color={color} />,
|
title: "Beranda",
|
||||||
}}
|
tabBarIcon: ({ color }) => <IconHome color={color} />,
|
||||||
/>
|
}}
|
||||||
<Tabs.Screen
|
/>
|
||||||
name="status"
|
<Tabs.Screen
|
||||||
options={{
|
name="status"
|
||||||
title: "Status",
|
options={{
|
||||||
tabBarIcon: ({ color }) => <IconStatus color={color} />,
|
title: "Status",
|
||||||
}}
|
tabBarIcon: ({ color }) => <IconStatus color={color} />,
|
||||||
/>
|
}}
|
||||||
<Tabs.Screen
|
/>
|
||||||
name="archive"
|
<Tabs.Screen
|
||||||
options={{
|
name="archive"
|
||||||
title: "Arsip",
|
options={{
|
||||||
tabBarIcon: ({ color }) => (
|
title: "Arsip",
|
||||||
<Ionicons size={20} name="archive" color={color} />
|
tabBarIcon: ({ color }) => (
|
||||||
),
|
<Ionicons size={20} name="archive" color={color} />
|
||||||
}}
|
),
|
||||||
/>
|
}}
|
||||||
</Tabs>
|
/>
|
||||||
|
</Tabs>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,14 +9,17 @@ import {
|
|||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import { dummyMasterStatus } from "@/lib/dummy-data/_master/status";
|
import { dummyMasterStatus } from "@/lib/dummy-data/_master/status";
|
||||||
import { apiJobGetByStatus } from "@/service/api-client/api-job";
|
import { apiJobGetByStatus } from "@/service/api-client/api-job";
|
||||||
import { useFocusEffect } from "expo-router";
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export default function JobStatus() {
|
export default function JobStatus() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
const { status } = useLocalSearchParams<{ status?: string }>();
|
||||||
|
console.log("STATUS", status);
|
||||||
|
|
||||||
const [activeCategory, setActiveCategory] = useState<string | null>(
|
const [activeCategory, setActiveCategory] = useState<string | null>(
|
||||||
"publish"
|
status || "publish"
|
||||||
);
|
);
|
||||||
const [listData, setListData] = useState<any[]>([]);
|
const [listData, setListData] = useState<any[]>([]);
|
||||||
const [isLoadList, setIsLoadList] = useState(false);
|
const [isLoadList, setIsLoadList] = useState(false);
|
||||||
@@ -60,25 +63,29 @@ export default function JobStatus() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewWrapper headerComponent={scrollComponent} hideFooter>
|
<>
|
||||||
{isLoadList ? (
|
<ViewWrapper headerComponent={scrollComponent} hideFooter>
|
||||||
<LoaderCustom />
|
{isLoadList ? (
|
||||||
) : _.isEmpty(listData) ? (
|
<LoaderCustom />
|
||||||
<TextCustom align="center">Tidak ada data {activeCategory}</TextCustom>
|
) : _.isEmpty(listData) ? (
|
||||||
) : (
|
<TextCustom align="center">
|
||||||
listData.map((e, i) => (
|
Tidak ada data {activeCategory}
|
||||||
<BaseBox
|
</TextCustom>
|
||||||
key={i}
|
) : (
|
||||||
paddingTop={20}
|
listData.map((e, i) => (
|
||||||
paddingBottom={20}
|
<BaseBox
|
||||||
href={`/job/${e?.id}/${activeCategory}/detail`}
|
key={i}
|
||||||
>
|
paddingTop={20}
|
||||||
<TextCustom align="center" bold truncate size="large">
|
paddingBottom={20}
|
||||||
{e?.title}
|
href={`/job/${e?.id}/${activeCategory}/detail`}
|
||||||
</TextCustom>
|
>
|
||||||
</BaseBox>
|
<TextCustom align="center" bold truncate size="large">
|
||||||
))
|
{e?.title}
|
||||||
)}
|
</TextCustom>
|
||||||
</ViewWrapper>
|
</BaseBox>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export default function JobDetailStatus() {
|
|||||||
<StackCustom gap={"xs"}>
|
<StackCustom gap={"xs"}>
|
||||||
{data &&
|
{data &&
|
||||||
data?.catatan &&
|
data?.catatan &&
|
||||||
(status === "draft" || status === "rejected") && (
|
(status === "draft" || status === "reject") && (
|
||||||
<ReportBox text={data?.catatan} />
|
<ReportBox text={data?.catatan} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ export default function JobDetail() {
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
const response = await apiJobGetOne({ id: id as string });
|
const response = await apiJobGetOne({ id: id as string });
|
||||||
|
|
||||||
|
console.log("DATA", JSON.stringify(response.data, null,2));
|
||||||
|
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { useState } from "react";
|
|||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function JobCreate() {
|
export default function JobCreate() {
|
||||||
const nextUrl = "/(application)/(user)/job/(tabs)/status";
|
const nextUrl = "/(application)/(user)/job/(tabs)/status?status=review";
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [image, setImage] = useState<string | null>(null);
|
const [image, setImage] = useState<string | null>(null);
|
||||||
|
|||||||
@@ -1,79 +1,101 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
|
AlertDefaultSystem,
|
||||||
|
BackButton,
|
||||||
BaseBox,
|
BaseBox,
|
||||||
Grid,
|
DrawerCustom,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
NewWrapper,
|
||||||
ScrollableCustom,
|
ScrollableCustom,
|
||||||
StackCustom,
|
StackCustom,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { IconDot } from "@/components/_Icon/IconComponent";
|
||||||
import { useState } from "react";
|
import ListSkeletonComponent from "@/components/_ShareComponent/ListSkeletonComponent";
|
||||||
import { View } from "react-native";
|
import NoDataText from "@/components/_ShareComponent/NoDataText";
|
||||||
|
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||||
const categories = [
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
{ value: "all", label: "Semua" },
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
{ value: "event", label: "Event" },
|
import { useNotificationStore } from "@/hooks/use-notification-store";
|
||||||
{ value: "job", label: "Job" },
|
import { apiGetNotificationsById } from "@/service/api-notifications";
|
||||||
{ value: "voting", label: "Voting" },
|
import { listOfcategoriesAppNotification } from "@/types/type-notification-category";
|
||||||
{ value: "donasi", label: "Donasi" },
|
import { formatChatTime } from "@/utils/formatChatTime";
|
||||||
{ value: "investasi", label: "Investasi" },
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
{ value: "forum", label: "Forum" },
|
import { router, Stack, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
{ value: "collaboration", label: "Collaboration" },
|
import _ from "lodash";
|
||||||
];
|
import { useCallback, useState } from "react";
|
||||||
|
import { RefreshControl, View } from "react-native";
|
||||||
|
|
||||||
const selectedCategory = (value: string) => {
|
const selectedCategory = (value: string) => {
|
||||||
const category = categories.find((c) => c.value === value);
|
const category = listOfcategoriesAppNotification.find(
|
||||||
|
(c) => c.value === value
|
||||||
|
);
|
||||||
return category?.label;
|
return category?.label;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fixPath = ({
|
||||||
|
deepLink,
|
||||||
|
categoryApp,
|
||||||
|
}: {
|
||||||
|
deepLink: string;
|
||||||
|
categoryApp: string;
|
||||||
|
}) => {
|
||||||
|
if (categoryApp === "OTHER") {
|
||||||
|
return deepLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
const separator = deepLink.includes("?") ? "&" : "?";
|
||||||
|
|
||||||
|
const fixedPath = `${deepLink}${separator}from=notifications&category=${_.lowerCase(
|
||||||
|
categoryApp
|
||||||
|
)}`;
|
||||||
|
|
||||||
|
console.log("Fix Path", fixedPath);
|
||||||
|
|
||||||
|
return fixedPath;
|
||||||
|
};
|
||||||
|
|
||||||
const BoxNotification = ({
|
const BoxNotification = ({
|
||||||
index,
|
data,
|
||||||
activeCategory,
|
activeCategory,
|
||||||
}: {
|
}: {
|
||||||
index: number;
|
data: any;
|
||||||
activeCategory: string | null;
|
activeCategory: string | null;
|
||||||
}) => {
|
}) => {
|
||||||
|
// console.log("DATA NOTIFICATION", JSON.stringify(data, null, 2));
|
||||||
|
const { markAsRead } = useNotificationStore();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<BaseBox
|
<BaseBox
|
||||||
onPress={() =>
|
backgroundColor={data.isRead ? AccentColor.darkblue : AccentColor.blue}
|
||||||
console.log(
|
onPress={() => {
|
||||||
"Notification >",
|
// console.log(
|
||||||
selectedCategory(activeCategory as string)
|
// "Notification >",
|
||||||
)
|
// selectedCategory(activeCategory as string)
|
||||||
}
|
// );
|
||||||
|
const newPath = fixPath({
|
||||||
|
deepLink: data.deepLink,
|
||||||
|
categoryApp: data.kategoriApp,
|
||||||
|
});
|
||||||
|
|
||||||
|
router.navigate(newPath as any);
|
||||||
|
selectedCategory(activeCategory as string);
|
||||||
|
|
||||||
|
if (!data.isRead) {
|
||||||
|
markAsRead(data.id);
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<TextCustom bold>
|
<TextCustom truncate={2} bold>
|
||||||
# {selectedCategory(activeCategory as string)}
|
{data.title}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
|
|
||||||
<View
|
<TextCustom truncate={2}>{data.pesan}</TextCustom>
|
||||||
style={{
|
|
||||||
borderBottomColor: MainColor.white_gray,
|
|
||||||
borderBottomWidth: 1,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TextCustom truncate={2}>
|
<TextCustom size="small" color="gray">
|
||||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Sint odio
|
{formatChatTime(data.createdAt)}
|
||||||
unde quidem voluptate quam culpa sequi molestias ipsa corrupti id,
|
|
||||||
soluta, nostrum adipisci similique, et illo asperiores deleniti eum
|
|
||||||
labore.
|
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
|
|
||||||
<Grid>
|
|
||||||
<Grid.Col span={6}>
|
|
||||||
<TextCustom size="small" color="gray">
|
|
||||||
{index + 1} Agustus 2025
|
|
||||||
</TextCustom>
|
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col span={6} style={{ alignItems: "flex-end" }}>
|
|
||||||
<TextCustom size="small" color="gray">
|
|
||||||
Belum lihat
|
|
||||||
</TextCustom>
|
|
||||||
</Grid.Col>
|
|
||||||
</Grid>
|
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
</>
|
</>
|
||||||
@@ -81,31 +103,146 @@ const BoxNotification = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function Notifications() {
|
export default function Notifications() {
|
||||||
const [activeCategory, setActiveCategory] = useState<string | null>("all");
|
const { user } = useAuth();
|
||||||
|
const { category } = useLocalSearchParams<{ category?: string }>();
|
||||||
|
const [activeCategory, setActiveCategory] = useState<string | null>(
|
||||||
|
category || "event"
|
||||||
|
);
|
||||||
|
const [listData, setListData] = useState<any[]>([]);
|
||||||
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
|
||||||
|
const { markAsReadAll } = useNotificationStore();
|
||||||
|
|
||||||
const handlePress = (item: any) => {
|
const handlePress = (item: any) => {
|
||||||
setActiveCategory(item.value);
|
setActiveCategory(item.value);
|
||||||
// tambahkan logika lain seperti filter dsb.
|
// tambahkan logika lain seperti filter dsb.
|
||||||
};
|
};
|
||||||
return (
|
|
||||||
<ViewWrapper
|
useFocusEffect(
|
||||||
headerComponent={
|
useCallback(() => {
|
||||||
<ScrollableCustom
|
fecthData();
|
||||||
data={categories.map((e, i) => ({
|
}, [activeCategory])
|
||||||
id: i,
|
);
|
||||||
label: e.label,
|
|
||||||
value: e.value,
|
const fecthData = async () => {
|
||||||
}))}
|
try {
|
||||||
onButtonPress={handlePress}
|
setLoading(true);
|
||||||
activeId={activeCategory as string}
|
const response = await apiGetNotificationsById({
|
||||||
/>
|
id: user?.id as any,
|
||||||
|
category: activeCategory as any,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setListData(response.data);
|
||||||
|
} else {
|
||||||
|
setListData([]);
|
||||||
}
|
}
|
||||||
>
|
} catch (error) {
|
||||||
{Array.from({ length: 20 }).map((e, i) => (
|
console.log("Error Notification", error);
|
||||||
<View key={i}>
|
} finally {
|
||||||
<BoxNotification index={i} activeCategory={activeCategory as any} />
|
setLoading(false);
|
||||||
</View>
|
}
|
||||||
))}
|
};
|
||||||
</ViewWrapper>
|
|
||||||
|
const onRefresh = () => {
|
||||||
|
setRefreshing(true);
|
||||||
|
fecthData();
|
||||||
|
setRefreshing(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: "Notifikasi",
|
||||||
|
headerLeft: () => <BackButton />,
|
||||||
|
headerRight: () => (
|
||||||
|
<IconDot
|
||||||
|
color={MainColor.yellow}
|
||||||
|
onPress={() => setOpenDrawer(true)}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<NewWrapper
|
||||||
|
headerComponent={
|
||||||
|
<ScrollableCustom
|
||||||
|
data={listOfcategoriesAppNotification.map((e, i) => ({
|
||||||
|
id: i,
|
||||||
|
label: e.label,
|
||||||
|
value: e.value,
|
||||||
|
}))}
|
||||||
|
onButtonPress={handlePress}
|
||||||
|
activeId={activeCategory as string}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
refreshControl={
|
||||||
|
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<ListSkeletonComponent />
|
||||||
|
) : _.isEmpty(listData) ? (
|
||||||
|
<NoDataText text="Belum ada notifikasi" />
|
||||||
|
) : (
|
||||||
|
listData.map((e, i) => (
|
||||||
|
<View key={i}>
|
||||||
|
<BoxNotification
|
||||||
|
data={e}
|
||||||
|
activeCategory={activeCategory as any}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</NewWrapper>
|
||||||
|
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
label: "Tandai Semua Dibaca",
|
||||||
|
value: "read-all",
|
||||||
|
icon: (
|
||||||
|
<Ionicons
|
||||||
|
name="reader-outline"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
path: "",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={(item: any) => {
|
||||||
|
console.log("Item", item.value);
|
||||||
|
if (item.value === "read-all") {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Tandai Semua Dibaca",
|
||||||
|
message:
|
||||||
|
"Apakah Anda yakin ingin menandai semua notifikasi dibaca?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Ya",
|
||||||
|
onPressRight: () => {
|
||||||
|
markAsReadAll(user?.id as any);
|
||||||
|
const data = _.cloneDeep(listData);
|
||||||
|
data.forEach((e) => {
|
||||||
|
e.isRead = true;
|
||||||
|
});
|
||||||
|
setListData(data);
|
||||||
|
onRefresh();
|
||||||
|
setOpenDrawer(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,7 +139,9 @@ const ButtonnDot = ({
|
|||||||
isUserCheck: boolean;
|
isUserCheck: boolean;
|
||||||
logout: () => Promise<void>;
|
logout: () => Promise<void>;
|
||||||
}) => {
|
}) => {
|
||||||
const isId = id === undefined || id === null;
|
console.log("[ID] >>", id);
|
||||||
|
|
||||||
|
const isId = id === undefined || id === "undefined";
|
||||||
|
|
||||||
if (isId) {
|
if (isId) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
75
app/(application)/(user)/test-notifications.tsx
Normal file
75
app/(application)/(user)/test-notifications.tsx
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import {
|
||||||
|
ButtonCustom,
|
||||||
|
NewWrapper,
|
||||||
|
StackCustom,
|
||||||
|
TextInputCustom,
|
||||||
|
} from "@/components";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
import { apiNotificationsSend } from "@/service/api-notifications";
|
||||||
|
import { useState } from "react";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
|
export default function TestNotification() {
|
||||||
|
const { user } = useAuth();
|
||||||
|
const [data, setData] = useState("");
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
try {
|
||||||
|
console.log("[Data Dikirim]", data);
|
||||||
|
setLoading(true);
|
||||||
|
const response = await apiNotificationsSend({
|
||||||
|
data: {
|
||||||
|
title: "Test Notification !!",
|
||||||
|
body: data,
|
||||||
|
userLoginId: user?.id || "",
|
||||||
|
appId: "hipmi",
|
||||||
|
status: "publish",
|
||||||
|
kategoriApp: "JOB",
|
||||||
|
type: "announcement",
|
||||||
|
deepLink: "/job/cmhjz8u3h0005cfaxezyeilrr",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
console.log("[RES SEND NOTIF]", JSON.stringify(response, null, 2));
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Notifikasi berhasil dikirim",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal mengirim notifikasi",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR SEND NOTIF]", error);
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal mengirim notifikasi",
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<NewWrapper>
|
||||||
|
<StackCustom>
|
||||||
|
<TextInputCustom
|
||||||
|
required
|
||||||
|
label="Pesan"
|
||||||
|
placeholder="Masukkan pesan"
|
||||||
|
value={data}
|
||||||
|
onChangeText={(text) => setData(text)}
|
||||||
|
/>
|
||||||
|
<ButtonCustom onPress={handleSubmit} disabled={loading}>
|
||||||
|
Kirim
|
||||||
|
</ButtonCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</NewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,13 +1,37 @@
|
|||||||
import {
|
import {
|
||||||
IconContribution,
|
IconContribution,
|
||||||
IconHistory,
|
IconHistory,
|
||||||
IconHome,
|
IconHome,
|
||||||
IconStatus,
|
IconStatus,
|
||||||
} from "@/components/_Icon";
|
} from "@/components/_Icon";
|
||||||
|
import BackButtonFromNotification from "@/components/Button/BackButtonFromNotification";
|
||||||
import { TabsStyles } from "@/styles/tabs-styles";
|
import { TabsStyles } from "@/styles/tabs-styles";
|
||||||
import { Tabs } from "expo-router";
|
import { Tabs, useLocalSearchParams, useNavigation, router } from "expo-router";
|
||||||
|
import { useLayoutEffect } from "react";
|
||||||
|
|
||||||
export default function VotingTabsLayout() {
|
export default function VotingTabsLayout() {
|
||||||
|
const navigation = useNavigation();
|
||||||
|
|
||||||
|
const { from, category } = useLocalSearchParams<{
|
||||||
|
from?: string;
|
||||||
|
category?: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
console.log("from", from);
|
||||||
|
console.log("category", category);
|
||||||
|
|
||||||
|
// Atur header secara dinamis
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
navigation.setOptions({
|
||||||
|
headerLeft: () => (
|
||||||
|
<BackButtonFromNotification
|
||||||
|
from={from as string}
|
||||||
|
category={category as string}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}, [from, router, navigation]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs screenOptions={TabsStyles}>
|
<Tabs screenOptions={TabsStyles}>
|
||||||
<Tabs.Screen
|
<Tabs.Screen
|
||||||
|
|||||||
@@ -12,15 +12,17 @@ import { useAuth } from "@/hooks/use-auth";
|
|||||||
import { dummyMasterStatus } from "@/lib/dummy-data/_master/status";
|
import { dummyMasterStatus } from "@/lib/dummy-data/_master/status";
|
||||||
import { apiVotingGetByStatus } from "@/service/api-client/api-voting";
|
import { apiVotingGetByStatus } from "@/service/api-client/api-voting";
|
||||||
import { dateTimeView } from "@/utils/dateTimeView";
|
import { dateTimeView } from "@/utils/dateTimeView";
|
||||||
import { useFocusEffect } from "expo-router";
|
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useCallback, useState } from "react";
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export default function VotingStatus() {
|
export default function VotingStatus() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
|
const { status } = useLocalSearchParams<{ status?: string }>();
|
||||||
|
|
||||||
const id = user?.id || "";
|
const id = user?.id || "";
|
||||||
const [activeCategory, setActiveCategory] = useState<string | null>(
|
const [activeCategory, setActiveCategory] = useState<string | null>(
|
||||||
"publish"
|
status || "publish"
|
||||||
);
|
);
|
||||||
|
|
||||||
const [listData, setListData] = useState([]);
|
const [listData, setListData] = useState([]);
|
||||||
@@ -86,8 +88,14 @@ export default function VotingStatus() {
|
|||||||
style={{ width: "70%", alignSelf: "center" }}
|
style={{ width: "70%", alignSelf: "center" }}
|
||||||
variant="light"
|
variant="light"
|
||||||
>
|
>
|
||||||
{item?.awalVote && dateTimeView({date: item?.awalVote, withoutTime: true})} -{" "}
|
{item?.awalVote &&
|
||||||
{item?.akhirVote && dateTimeView({date: item?.akhirVote, withoutTime: true})}
|
dateTimeView({
|
||||||
|
date: item?.awalVote,
|
||||||
|
withoutTime: true,
|
||||||
|
})}{" "}
|
||||||
|
-{" "}
|
||||||
|
{item?.akhirVote &&
|
||||||
|
dateTimeView({ date: item?.akhirVote, withoutTime: true })}
|
||||||
</BadgeCustom>
|
</BadgeCustom>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { IconArchive, IconContribution } from "@/components/_Icon";
|
import { IconArchive, IconContribution } from "@/components/_Icon";
|
||||||
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
import { IMenuDrawerItem } from "@/components/_Interface/types";
|
||||||
|
import CustomSkeleton from "@/components/_ShareComponent/SkeletonCustom";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import Voting_BoxDetailHasilVotingSection from "@/screens/Voting/BoxDetailHasilVotingSection";
|
import Voting_BoxDetailHasilVotingSection from "@/screens/Voting/BoxDetailHasilVotingSection";
|
||||||
import { Voting_BoxDetailPublishSection } from "@/screens/Voting/BoxDetailPublishSection";
|
import { Voting_BoxDetailPublishSection } from "@/screens/Voting/BoxDetailPublishSection";
|
||||||
@@ -22,13 +23,14 @@ import {
|
|||||||
apiVotingUpdateData,
|
apiVotingUpdateData,
|
||||||
} from "@/service/api-client/api-voting";
|
} from "@/service/api-client/api-voting";
|
||||||
import { today } from "@/utils/dateTimeView";
|
import { today } from "@/utils/dateTimeView";
|
||||||
|
import dayjs from "dayjs";
|
||||||
import {
|
import {
|
||||||
router,
|
router,
|
||||||
Stack,
|
Stack,
|
||||||
useFocusEffect,
|
useFocusEffect,
|
||||||
useLocalSearchParams,
|
useLocalSearchParams,
|
||||||
} from "expo-router";
|
} from "expo-router";
|
||||||
import React, { useCallback, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function VotingDetail() {
|
export default function VotingDetail() {
|
||||||
@@ -119,6 +121,23 @@ export default function VotingDetail() {
|
|||||||
setOpenDrawerPublish(false);
|
setOpenDrawerPublish(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const now = new Date().toISOString();
|
||||||
|
const isEventFinished = id && data?.akhirVote && dayjs(data.akhirVote).isBefore(now);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isEventFinished) {
|
||||||
|
router.replace(`/(application)/(user)/voting/${id}/history`);
|
||||||
|
}
|
||||||
|
}, [isEventFinished, id]);
|
||||||
|
|
||||||
|
if (isEventFinished) {
|
||||||
|
return (
|
||||||
|
<ViewWrapper>
|
||||||
|
<CustomSkeleton />
|
||||||
|
</ViewWrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export default function VotingCreate() {
|
|||||||
type: "success",
|
type: "success",
|
||||||
text1: "Data berhasil disimpan",
|
text1: "Data berhasil disimpan",
|
||||||
});
|
});
|
||||||
router.replace("/(application)/(user)/voting/(tabs)/status");
|
router.replace("/(application)/(user)/voting/(tabs)/status?status=review");
|
||||||
} else {
|
} else {
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: "error",
|
type: "error",
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
AlertDefaultSystem,
|
AlertDefaultSystem,
|
||||||
BoxButtonOnFooter,
|
BoxButtonOnFooter,
|
||||||
ButtonCenteredOnly,
|
|
||||||
ButtonCustom,
|
ButtonCustom,
|
||||||
InformationBox,
|
InformationBox,
|
||||||
NewWrapper,
|
NewWrapper,
|
||||||
StackCustom,
|
StackCustom
|
||||||
ViewWrapper,
|
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
|||||||
@@ -1,16 +1,29 @@
|
|||||||
import { BackButton } from "@/components";
|
import { BackButton } from "@/components";
|
||||||
|
import BackgroundNotificationHandler from "@/components/Notification/BackgroundNotificationHandler";
|
||||||
|
import NotificationInitializer from "@/components/Notification/NotificationInitializer";
|
||||||
|
import { NotificationProvider } from "@/hooks/use-notification-store";
|
||||||
import { HeaderStyles } from "@/styles/header-styles";
|
import { HeaderStyles } from "@/styles/header-styles";
|
||||||
import { Stack } from "expo-router";
|
import { Stack } from "expo-router";
|
||||||
|
|
||||||
export default function ApplicationLayout() {
|
export default function ApplicationLayout() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<NotificationProvider>
|
||||||
|
<NotificationInitializer />
|
||||||
|
<BackgroundNotificationHandler />
|
||||||
|
<ApplicationStack />
|
||||||
|
</NotificationProvider>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ApplicationStack() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack screenOptions={HeaderStyles}>
|
<Stack screenOptions={HeaderStyles}>
|
||||||
<Stack.Screen name="(user)" options={{ headerShown: false }} />
|
<Stack.Screen name="(user)" options={{ headerShown: false }} />
|
||||||
<Stack.Screen name="admin" options={{ headerShown: false }} />
|
<Stack.Screen name="admin" options={{ headerShown: false }} />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{/* Take Picture */}
|
{/* Take Picture */}
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="(image)/take-picture/[id]/index"
|
name="(image)/take-picture/[id]/index"
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
ICON_SIZE_XLARGE,
|
ICON_SIZE_XLARGE,
|
||||||
} from "@/constants/constans-value";
|
} from "@/constants/constans-value";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
import AdminNotificationBell from "@/screens/Admin/AdminNotificationBell";
|
||||||
import {
|
import {
|
||||||
adminListMenu,
|
adminListMenu,
|
||||||
superAdminListMenu,
|
superAdminListMenu,
|
||||||
@@ -192,11 +193,12 @@ export default function AdminLayout() {
|
|||||||
label: "Notifikasi",
|
label: "Notifikasi",
|
||||||
value: "notification",
|
value: "notification",
|
||||||
icon: (
|
icon: (
|
||||||
<Ionicons
|
// <Ionicons
|
||||||
name="notifications"
|
// name="notifications"
|
||||||
size={ICON_SIZE_SMALL}
|
// size={ICON_SIZE_SMALL}
|
||||||
color={MainColor.white}
|
// color={MainColor.white}
|
||||||
/>
|
// />
|
||||||
|
<AdminNotificationBell/>
|
||||||
),
|
),
|
||||||
path: "/admin/notification",
|
path: "/admin/notification",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ export default function AdminEventDetail() {
|
|||||||
const deepLinkURL = `${DEEP_LINK_URL}/event/${id}/confirmation?userId=${user?.id}`;
|
const deepLinkURL = `${DEEP_LINK_URL}/event/${id}/confirmation?userId=${user?.id}`;
|
||||||
const deepLinkURLDEV = `${DEEP_LINK_URL}/--/event/${id}/confirmation?userId=${user?.id}`;
|
const deepLinkURLDEV = `${DEEP_LINK_URL}/--/event/${id}/confirmation?userId=${user?.id}`;
|
||||||
|
|
||||||
const isDevLink = process.env.NODE_ENV === "development" ? deepLinkURLDEV : deepLinkURL;
|
const isDevLink =
|
||||||
|
process.env.NODE_ENV === "development" ? deepLinkURLDEV : deepLinkURL;
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
@@ -126,6 +126,7 @@ export default function AdminEventDetail() {
|
|||||||
const response = await funUpdateStatusEvent({
|
const response = await funUpdateStatusEvent({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
changeStatus: "publish",
|
changeStatus: "publish",
|
||||||
|
data: { catatan: "", senderId: user?.id as string },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import { funUpdateStatusEvent } from "@/screens/Admin/Event/funUpdateStatus";
|
import { funUpdateStatusEvent } from "@/screens/Admin/Event/funUpdateStatus";
|
||||||
import { apiAdminEventById } from "@/service/api-admin/api-admin-event";
|
import { apiAdminEventById } from "@/service/api-admin/api-admin-event";
|
||||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
@@ -14,9 +15,13 @@ import { useCallback, useState } from "react";
|
|||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminEventRejectInput() {
|
export default function AdminEventRejectInput() {
|
||||||
|
const { user } = useAuth();
|
||||||
const { id, status } = useLocalSearchParams();
|
const { id, status } = useLocalSearchParams();
|
||||||
|
|
||||||
const [data, setData] = useState<any>("");
|
const [data, setData] = useState<any>({
|
||||||
|
catatan: "",
|
||||||
|
senderId: "",
|
||||||
|
});
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
@@ -45,10 +50,16 @@ export default function AdminEventRejectInput() {
|
|||||||
}) => {
|
}) => {
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
|
const newData = {
|
||||||
|
catatan: data,
|
||||||
|
senderId: user?.id as string,
|
||||||
|
};
|
||||||
|
|
||||||
const response = await funUpdateStatusEvent({
|
const response = await funUpdateStatusEvent({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
changeStatus,
|
changeStatus,
|
||||||
data: data,
|
data: newData,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
|
|||||||
@@ -15,12 +15,11 @@ import { IconDot, IconView } from "@/components/_Icon/IconComponent";
|
|||||||
import { IconTrash } from "@/components/_Icon/IconTrash";
|
import { IconTrash } from "@/components/_Icon/IconTrash";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
||||||
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
|
|
||||||
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
|
|
||||||
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||||
import { GridSpan_NewComponent } from "@/components/_ShareComponent/GridSpan_NewComponent";
|
import { GridSpan_NewComponent } from "@/components/_ShareComponent/GridSpan_NewComponent";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import {
|
import {
|
||||||
apiAdminForumCommentById,
|
apiAdminForumCommentById,
|
||||||
apiAdminForumDeactivateComment,
|
apiAdminForumDeactivateComment,
|
||||||
@@ -35,6 +34,7 @@ import Toast from "react-native-toast-message";
|
|||||||
|
|
||||||
export default function AdminForumReportComment() {
|
export default function AdminForumReportComment() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
|
const { user } = useAuth();
|
||||||
const [data, setData] = useState<any | null>(null);
|
const [data, setData] = useState<any | null>(null);
|
||||||
const [listReport, setListReport] = useState<any[] | null>(null);
|
const [listReport, setListReport] = useState<any[] | null>(null);
|
||||||
const [loadList, setLoadList] = useState(false);
|
const [loadList, setLoadList] = useState(false);
|
||||||
@@ -111,9 +111,13 @@ export default function AdminForumReportComment() {
|
|||||||
|
|
||||||
<AdminComp_BoxTitle title="Daftar Report Komentar" />
|
<AdminComp_BoxTitle title="Daftar Report Komentar" />
|
||||||
|
|
||||||
<StackCustom gap={"sm"}>
|
<StackCustom gap={"sm"}>
|
||||||
<GridSpan_NewComponent
|
<GridSpan_NewComponent
|
||||||
text1={<TextCustom bold align="center">Aksi</TextCustom>}
|
text1={
|
||||||
|
<TextCustom bold align="center">
|
||||||
|
Aksi
|
||||||
|
</TextCustom>
|
||||||
|
}
|
||||||
text2={<TextCustom bold>Pelapor</TextCustom>}
|
text2={<TextCustom bold>Pelapor</TextCustom>}
|
||||||
text3={<TextCustom bold>Kategori Report</TextCustom>}
|
text3={<TextCustom bold>Kategori Report</TextCustom>}
|
||||||
/>
|
/>
|
||||||
@@ -129,22 +133,24 @@ export default function AdminForumReportComment() {
|
|||||||
<View key={index}>
|
<View key={index}>
|
||||||
<GridSpan_NewComponent
|
<GridSpan_NewComponent
|
||||||
text1={
|
text1={
|
||||||
<CenterCustom>
|
<CenterCustom>
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
icon={<IconView size={ICON_SIZE_BUTTON} color="black" />}
|
icon={
|
||||||
onPress={() => {
|
<IconView size={ICON_SIZE_BUTTON} color="black" />
|
||||||
setOpenDrawerAction(true);
|
}
|
||||||
setSelectedReport({
|
onPress={() => {
|
||||||
id: item.id,
|
setOpenDrawerAction(true);
|
||||||
username: item.User?.username,
|
setSelectedReport({
|
||||||
kategori: item.ForumMaster_KategoriReport?.title,
|
id: item.id,
|
||||||
keterangan:
|
username: item.User?.username,
|
||||||
item.ForumMaster_KategoriReport?.deskripsi,
|
kategori: item.ForumMaster_KategoriReport?.title,
|
||||||
deskripsi: item.deskripsi,
|
keterangan:
|
||||||
});
|
item.ForumMaster_KategoriReport?.deskripsi,
|
||||||
}}
|
deskripsi: item.deskripsi,
|
||||||
/>
|
});
|
||||||
</CenterCustom>
|
}}
|
||||||
|
/>
|
||||||
|
</CenterCustom>
|
||||||
}
|
}
|
||||||
text2={
|
text2={
|
||||||
<TextCustom truncate={1}>
|
<TextCustom truncate={1}>
|
||||||
@@ -188,15 +194,18 @@ export default function AdminForumReportComment() {
|
|||||||
onPressRight: async () => {
|
onPressRight: async () => {
|
||||||
const deleteComment = await apiAdminForumDeactivateComment({
|
const deleteComment = await apiAdminForumDeactivateComment({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
|
data: {
|
||||||
|
senderId: user?.id as string,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!deleteComment.success) {
|
// if (!deleteComment.success) {
|
||||||
Toast.show({
|
// Toast.show({
|
||||||
type: "error",
|
// type: "error",
|
||||||
text1: "Komentar gagal dihapus",
|
// text1: "Komentar gagal dihapus",
|
||||||
});
|
// });
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
setOpenDrawer(false);
|
setOpenDrawer(false);
|
||||||
Toast.show({
|
Toast.show({
|
||||||
|
|||||||
@@ -16,12 +16,11 @@ import { IconDot, IconView } from "@/components/_Icon/IconComponent";
|
|||||||
import { IconTrash } from "@/components/_Icon/IconTrash";
|
import { IconTrash } from "@/components/_Icon/IconTrash";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
|
||||||
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
|
|
||||||
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
|
|
||||||
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||||
import { GridSpan_NewComponent } from "@/components/_ShareComponent/GridSpan_NewComponent";
|
import { GridSpan_NewComponent } from "@/components/_ShareComponent/GridSpan_NewComponent";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import {
|
import {
|
||||||
apiAdminForumDeactivatePosting,
|
apiAdminForumDeactivatePosting,
|
||||||
apiAdminForumListReportPostingById,
|
apiAdminForumListReportPostingById,
|
||||||
@@ -35,6 +34,7 @@ import { Divider } from "react-native-paper";
|
|||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminForumReportPosting() {
|
export default function AdminForumReportPosting() {
|
||||||
|
const { user } = useAuth();
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
const [openDrawerPage, setOpenDrawerPage] = useState(false);
|
const [openDrawerPage, setOpenDrawerPage] = useState(false);
|
||||||
const [openDrawerAction, setOpenDrawerAction] = useState(false);
|
const [openDrawerAction, setOpenDrawerAction] = useState(false);
|
||||||
@@ -215,6 +215,9 @@ export default function AdminForumReportPosting() {
|
|||||||
onPressRight: async () => {
|
onPressRight: async () => {
|
||||||
const response = await apiAdminForumDeactivatePosting({
|
const response = await apiAdminForumDeactivatePosting({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
|
data: {
|
||||||
|
senderId: user?.id as string,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export default function AdminForumReportPosting() {
|
|||||||
<GridSpan_NewComponent
|
<GridSpan_NewComponent
|
||||||
text1={
|
text1={
|
||||||
<TextCustom bold truncate>
|
<TextCustom bold truncate>
|
||||||
Username
|
Pelapor
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
}
|
}
|
||||||
text2={
|
text2={
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButt
|
|||||||
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
||||||
import AdminButtonReview from "@/components/_ShareComponent/Admin/ButtonReview";
|
import AdminButtonReview from "@/components/_ShareComponent/Admin/ButtonReview";
|
||||||
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||||
|
import CustomSkeleton from "@/components/_ShareComponent/SkeletonCustom";
|
||||||
import ReportBox from "@/components/Box/ReportBox";
|
import ReportBox from "@/components/Box/ReportBox";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
|
||||||
@@ -28,6 +29,7 @@ import {
|
|||||||
apiAdminInvestmentDetailById,
|
apiAdminInvestmentDetailById,
|
||||||
} from "@/service/api-admin/api-admin-investment";
|
} from "@/service/api-admin/api-admin-investment";
|
||||||
import { colorBadgeStatus } from "@/utils/colorBadge";
|
import { colorBadgeStatus } from "@/utils/colorBadge";
|
||||||
|
import { countDownAndCondition } from "@/utils/countDownAndCondition";
|
||||||
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
@@ -40,91 +42,41 @@ export default function AdminInvestmentDetail() {
|
|||||||
|
|
||||||
const [data, setData] = React.useState<any | null>(null);
|
const [data, setData] = React.useState<any | null>(null);
|
||||||
const [isLoading, setLoading] = React.useState(false);
|
const [isLoading, setLoading] = React.useState(false);
|
||||||
|
const [remind, setRemind] = React.useState({
|
||||||
|
sisa: 0,
|
||||||
|
reminder: false,
|
||||||
|
});
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
React.useCallback(() => {
|
React.useCallback(() => {
|
||||||
onLoadData();
|
onLoadData();
|
||||||
}, [id])
|
}, [id]),
|
||||||
);
|
);
|
||||||
|
|
||||||
const onLoadData = async () => {
|
const onLoadData = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await apiAdminInvestmentDetailById({ id: id as string });
|
const response = await apiAdminInvestmentDetailById({ id: id as string });
|
||||||
// console.log("[GETONE INVEST]", JSON.stringify(response, null, 2));
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
|
|
||||||
|
const duration = response?.data?.MasterPencarianInvestor?.name;
|
||||||
|
const publishTime = response?.data?.countDown;
|
||||||
|
|
||||||
|
const countDown = countDownAndCondition({
|
||||||
|
duration: duration,
|
||||||
|
publishTime: publishTime
|
||||||
|
});
|
||||||
|
|
||||||
|
setRemind({
|
||||||
|
sisa: countDown.durationDay,
|
||||||
|
reminder: countDown.reminder,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log("Error", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const listData = [
|
|
||||||
{
|
|
||||||
label: "Username",
|
|
||||||
value: (data && data?.author?.username) || "-",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Judul",
|
|
||||||
value: (data && data?.title) || "-",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Status",
|
|
||||||
value:
|
|
||||||
data && data?.MasterStatusInvestasi?.name ? (
|
|
||||||
<BadgeCustom
|
|
||||||
color={colorBadgeStatus({
|
|
||||||
status: data?.MasterStatusInvestasi?.name as string,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{_.startCase(data?.MasterStatusInvestasi?.name as string)}
|
|
||||||
</BadgeCustom>
|
|
||||||
) : (
|
|
||||||
"-"
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Dana Dibutuhkan",
|
|
||||||
value: `Rp. ${
|
|
||||||
(data && data?.targetDana && formatCurrencyDisplay(data?.targetDana)) ||
|
|
||||||
"-"
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Harga Perlembar",
|
|
||||||
value: `Rp. ${
|
|
||||||
(data &&
|
|
||||||
data?.hargaLembar &&
|
|
||||||
formatCurrencyDisplay(data?.hargaLembar)) ||
|
|
||||||
"-"
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Total Lembar",
|
|
||||||
value:
|
|
||||||
(data &&
|
|
||||||
data?.totalLembar &&
|
|
||||||
formatCurrencyDisplay(data?.totalLembar)) ||
|
|
||||||
"-",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "ROI",
|
|
||||||
value: `${(data && data?.roi && data?.roi) || 0} %`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Pembagian Deviden",
|
|
||||||
value: (data && data?.MasterPembagianDeviden?.name) + " bulan" || "-",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Jadwal Pembagian",
|
|
||||||
value: (data && data?.MasterPeriodeDeviden?.name) || "-",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Pencarian Investor",
|
|
||||||
value: (data && data?.MasterPencarianInvestor?.name) + " hari" || "-",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const handlerSubmitPublish = async () => {
|
const handlerSubmitPublish = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -134,7 +86,6 @@ export default function AdminInvestmentDetail() {
|
|||||||
data: data,
|
data: data,
|
||||||
});
|
});
|
||||||
|
|
||||||
// console.log("[GET ON INVEST]", JSON.stringify(response, null, 2));
|
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: "error",
|
type: "error",
|
||||||
@@ -164,6 +115,16 @@ export default function AdminInvestmentDetail() {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewWrapper>
|
||||||
|
<CustomSkeleton height={200} />
|
||||||
|
</ViewWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper
|
<ViewWrapper
|
||||||
@@ -177,8 +138,8 @@ export default function AdminInvestmentDetail() {
|
|||||||
{status === "publish" && (
|
{status === "publish" && (
|
||||||
<BaseBox>
|
<BaseBox>
|
||||||
<ProgressCustom
|
<ProgressCustom
|
||||||
label={data && `${data.progress}%` || "0%"}
|
label={(data && `${data.progress}%`) || "0%"}
|
||||||
value={data && data.progress || 0}
|
value={(data && data.progress) || 0}
|
||||||
size="lg"
|
size="lg"
|
||||||
/>
|
/>
|
||||||
<Spacing />
|
<Spacing />
|
||||||
@@ -187,7 +148,8 @@ export default function AdminInvestmentDetail() {
|
|||||||
label={<TextCustom bold>Sisa Saham</TextCustom>}
|
label={<TextCustom bold>Sisa Saham</TextCustom>}
|
||||||
value={
|
value={
|
||||||
<TextCustom>
|
<TextCustom>
|
||||||
{data && formatCurrencyDisplay(data && data?.sisaLembar)} lembar
|
{data && formatCurrencyDisplay(data && data?.sisaLembar)}{" "}
|
||||||
|
lembar
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -206,13 +168,15 @@ export default function AdminInvestmentDetail() {
|
|||||||
<BaseBox>
|
<BaseBox>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<DummyLandscapeImage imageId={data?.imageId} />
|
<DummyLandscapeImage imageId={data?.imageId} />
|
||||||
{listData.map((item, i) => (
|
{listData({ data: data, reminder: remind.reminder })?.map(
|
||||||
<GridSpan_4_8
|
(item, i) => (
|
||||||
key={i}
|
<GridSpan_4_8
|
||||||
label={<TextCustom bold>{item.label}</TextCustom>}
|
key={i}
|
||||||
value={<TextCustom>{item.value}</TextCustom>}
|
label={<TextCustom bold>{item.label}</TextCustom>}
|
||||||
/>
|
value={<TextCustom>{item.value}</TextCustom>}
|
||||||
))}
|
/>
|
||||||
|
),
|
||||||
|
)}
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
|
|
||||||
@@ -230,7 +194,7 @@ export default function AdminInvestmentDetail() {
|
|||||||
}
|
}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push(
|
router.push(
|
||||||
`/(application)/(file)/${data?.prospektusFileId}`
|
`/(application)/(file)/${data?.prospektusFileId}`,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -259,7 +223,7 @@ export default function AdminInvestmentDetail() {
|
|||||||
}
|
}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push(
|
router.push(
|
||||||
`/(application)/(file)/${item?.fileId}`
|
`/(application)/(file)/${item?.fileId}`,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -299,8 +263,8 @@ export default function AdminInvestmentDetail() {
|
|||||||
onReject={() => {
|
onReject={() => {
|
||||||
router.push(
|
router.push(
|
||||||
`/admin/investment/${id}/reject-input?status=${_.lowerCase(
|
`/admin/investment/${id}/reject-input?status=${_.lowerCase(
|
||||||
data?.MasterStatusInvestasi?.name
|
data?.MasterStatusInvestasi?.name,
|
||||||
)}`
|
)}`,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -343,3 +307,67 @@ export default function AdminInvestmentDetail() {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const listData = ({ data, reminder }: { data: any; reminder: boolean }) => [
|
||||||
|
{
|
||||||
|
label: "Username",
|
||||||
|
value: (data && data?.author?.username) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Judul",
|
||||||
|
value: (data && data?.title) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Status",
|
||||||
|
value:
|
||||||
|
data && data?.MasterStatusInvestasi?.name ? (
|
||||||
|
<BadgeCustom
|
||||||
|
color={colorBadgeStatus({
|
||||||
|
status: reminder ? "periode berakhir" : "publish",
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{reminder
|
||||||
|
? "Periode Berakhir"
|
||||||
|
: _.startCase(data?.MasterStatusInvestasi?.name as string)}
|
||||||
|
</BadgeCustom>
|
||||||
|
) : (
|
||||||
|
"-"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Dana Dibutuhkan",
|
||||||
|
value: `Rp. ${
|
||||||
|
(data && data?.targetDana && formatCurrencyDisplay(data?.targetDana)) ||
|
||||||
|
"-"
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Harga Perlembar",
|
||||||
|
value: `Rp. ${
|
||||||
|
(data && data?.hargaLembar && formatCurrencyDisplay(data?.hargaLembar)) ||
|
||||||
|
"-"
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Total Lembar",
|
||||||
|
value:
|
||||||
|
(data && data?.totalLembar && formatCurrencyDisplay(data?.totalLembar)) ||
|
||||||
|
"-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "ROI",
|
||||||
|
value: `${(data && data?.roi && data?.roi) || 0} %`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Pembagian Deviden",
|
||||||
|
value: (data && data?.MasterPembagianDeviden?.name) + " bulan" || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Jadwal Pembagian",
|
||||||
|
value: (data && data?.MasterPeriodeDeviden?.name) || "-",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Pencarian Investor",
|
||||||
|
value: (data && data?.MasterPencarianInvestor?.name) + " hari" || "-",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButt
|
|||||||
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||||
import GridTwoView from "@/components/_ShareComponent/GridTwoView";
|
import GridTwoView from "@/components/_ShareComponent/GridTwoView";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import {
|
import {
|
||||||
apiAdminInvestmentGetOneInvoiceById,
|
apiAdminInvestmentGetOneInvoiceById,
|
||||||
apiAdminInvestmentUpdateInvoice,
|
apiAdminInvestmentUpdateInvoice,
|
||||||
@@ -25,6 +26,7 @@ import { useCallback, useState } from "react";
|
|||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminInvestmentTransactionDetail() {
|
export default function AdminInvestmentTransactionDetail() {
|
||||||
|
const { user } = useAuth();
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
const [data, setData] = useState<any | null>(null);
|
const [data, setData] = useState<any | null>(null);
|
||||||
const [isLoading, setLoading] = useState<boolean>(false);
|
const [isLoading, setLoading] = useState<boolean>(false);
|
||||||
@@ -32,7 +34,7 @@ export default function AdminInvestmentTransactionDetail() {
|
|||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
onLoadData();
|
onLoadData();
|
||||||
}, [id])
|
}, [id]),
|
||||||
);
|
);
|
||||||
|
|
||||||
const onLoadData = async () => {
|
const onLoadData = async () => {
|
||||||
@@ -40,7 +42,6 @@ export default function AdminInvestmentTransactionDetail() {
|
|||||||
const response = await apiAdminInvestmentGetOneInvoiceById({
|
const response = await apiAdminInvestmentGetOneInvoiceById({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
});
|
});
|
||||||
// console.log("[RESPONSE]", JSON.stringify(response, null, 2));
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
}
|
}
|
||||||
@@ -92,7 +93,7 @@ export default function AdminInvestmentTransactionDetail() {
|
|||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
router.push(
|
router.push(
|
||||||
`/(application)/(image)/preview-image/${data?.imageId}`
|
`/(application)/(image)/preview-image/${data?.imageId}`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -109,6 +110,13 @@ export default function AdminInvestmentTransactionDetail() {
|
|||||||
}: {
|
}: {
|
||||||
category: "accept" | "deny";
|
category: "accept" | "deny";
|
||||||
}) => {
|
}) => {
|
||||||
|
if (!user?.id) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal update status transaksi",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const response = await apiAdminInvestmentUpdateInvoice({
|
const response = await apiAdminInvestmentUpdateInvoice({
|
||||||
@@ -117,11 +125,10 @@ export default function AdminInvestmentTransactionDetail() {
|
|||||||
data: {
|
data: {
|
||||||
investasiId: data?.investasiId,
|
investasiId: data?.investasiId,
|
||||||
lembarTerbeli: data?.lembarTerbeli,
|
lembarTerbeli: data?.lembarTerbeli,
|
||||||
|
senderId: user?.id as any,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// console.log("[RESPONSE SUBMIT]", JSON.stringify(response, null, 2));
|
|
||||||
|
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: "error",
|
type: "error",
|
||||||
@@ -153,6 +160,7 @@ export default function AdminInvestmentTransactionDetail() {
|
|||||||
styleRight={{ paddingLeft: 10 }}
|
styleRight={{ paddingLeft: 10 }}
|
||||||
leftIcon={
|
leftIcon={
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
|
disabled={isLoading}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
backgroundColor={MainColor.red}
|
backgroundColor={MainColor.red}
|
||||||
textColor="white"
|
textColor="white"
|
||||||
@@ -175,6 +183,7 @@ export default function AdminInvestmentTransactionDetail() {
|
|||||||
}
|
}
|
||||||
rightIcon={
|
rightIcon={
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
|
disabled={isLoading}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
AlertDefaultSystem({
|
AlertDefaultSystem({
|
||||||
@@ -198,8 +207,8 @@ export default function AdminInvestmentTransactionDetail() {
|
|||||||
} else if (data?.StatusInvoice?.name === "Gagal") {
|
} else if (data?.StatusInvoice?.name === "Gagal") {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ButtonCustom textColor="red" onPress={() => router.back()}>
|
<ButtonCustom disabled onPress={() => router.back()}>
|
||||||
Gagal
|
Transaksi telah gagal
|
||||||
</ButtonCustom>
|
</ButtonCustom>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,34 +7,39 @@ import {
|
|||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
||||||
import { apiAdminInvestasiUpdateByStatus, apiAdminInvestmentDetailById } from "@/service/api-admin/api-admin-investment";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
import {
|
||||||
|
apiAdminInvestasiUpdateByStatus,
|
||||||
|
apiAdminInvestmentDetailById,
|
||||||
|
} from "@/service/api-admin/api-admin-investment";
|
||||||
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 Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminInvestmentRejectInput() {
|
export default function AdminInvestmentRejectInput() {
|
||||||
|
const { user } = useAuth();
|
||||||
const { id, status } = useLocalSearchParams();
|
const { id, status } = useLocalSearchParams();
|
||||||
console.log("[STATUS]", status);
|
console.log("[STATUS]", status);
|
||||||
const [value, setValue] = useState<any | null>(null);
|
const [value, setValue] = useState<any | null>(null);
|
||||||
const [isLoading , setLoading] = useState(false)
|
const [isLoading, setLoading] = useState(false);
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
onLoadData();
|
onLoadData();
|
||||||
}, [id])
|
}, [id])
|
||||||
);
|
);
|
||||||
|
|
||||||
const onLoadData = async () => {
|
const onLoadData = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await apiAdminInvestmentDetailById({ id: id as string });
|
const response = await apiAdminInvestmentDetailById({ id: id as string });
|
||||||
console.log("[DATA]", JSON.stringify(response, null, 2));
|
console.log("[DATA]", JSON.stringify(response, null, 2));
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setValue(response.data?.catatan);
|
setValue(response.data?.catatan);
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
}
|
||||||
};
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handlerSubmit = async () => {
|
const handlerSubmit = async () => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
@@ -45,12 +50,23 @@ export default function AdminInvestmentRejectInput() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!user?.id) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "User tidak ditemukan",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setLoading(true)
|
setLoading(true);
|
||||||
const response = await apiAdminInvestasiUpdateByStatus({
|
const response = await apiAdminInvestasiUpdateByStatus({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
status: "reject",
|
status: "reject",
|
||||||
data: value,
|
data: {
|
||||||
|
catatan: value,
|
||||||
|
senderId: user?.id as string,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("[RESPONSE]", JSON.stringify(response, null, 2));
|
console.log("[RESPONSE]", JSON.stringify(response, null, 2));
|
||||||
@@ -76,7 +92,7 @@ export default function AdminInvestmentRejectInput() {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(["ERROR"], error);
|
console.error(["ERROR"], error);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ import { Divider } from "react-native-paper";
|
|||||||
|
|
||||||
export default function AdminInvestmentStatus() {
|
export default function AdminInvestmentStatus() {
|
||||||
const { status } = useLocalSearchParams();
|
const { status } = useLocalSearchParams();
|
||||||
console.log("[STATUS]", status);
|
|
||||||
|
|
||||||
const [listData, setListData] = React.useState<any[] | null>(null);
|
const [listData, setListData] = React.useState<any[] | null>(null);
|
||||||
const [loadData, setLoadingData] = React.useState(false);
|
const [loadData, setLoadingData] = React.useState(false);
|
||||||
const [search, setSearch] = React.useState("");
|
const [search, setSearch] = React.useState("");
|
||||||
@@ -41,7 +39,7 @@ export default function AdminInvestmentStatus() {
|
|||||||
category: status as "publish" | "review" | "reject",
|
category: status as "publish" | "review" | "reject",
|
||||||
search,
|
search,
|
||||||
});
|
});
|
||||||
console.log("[LIST DATA]", JSON.stringify(response, null, 2));
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
setListData(response.data);
|
setListData(response.data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
|||||||
import AdminButtonReview from "@/components/_ShareComponent/Admin/ButtonReview";
|
import AdminButtonReview from "@/components/_ShareComponent/Admin/ButtonReview";
|
||||||
import ReportBox from "@/components/Box/ReportBox";
|
import ReportBox from "@/components/Box/ReportBox";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import funUpdateStatusJob from "@/screens/Admin/Job/funUpdateStatus";
|
import funUpdateStatusJob from "@/screens/Admin/Job/funUpdateStatus";
|
||||||
import { apiAdminJobGetById } from "@/service/api-admin/api-admin-job";
|
import { apiAdminJobGetById } from "@/service/api-admin/api-admin-job";
|
||||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
@@ -23,8 +24,10 @@ import { useCallback, useState } from "react";
|
|||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminJobDetailStatus() {
|
export default function AdminJobDetailStatus() {
|
||||||
|
const { user } = useAuth();
|
||||||
const { id, status } = useLocalSearchParams();
|
const { id, status } = useLocalSearchParams();
|
||||||
const [data, setData] = useState<any | null>(null);
|
const [data, setData] = useState<any | null>(null);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
@@ -92,6 +95,9 @@ export default function AdminJobDetailStatus() {
|
|||||||
const response = await funUpdateStatusJob({
|
const response = await funUpdateStatusJob({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
changeStatus,
|
changeStatus,
|
||||||
|
data: {
|
||||||
|
senderId: user?.id as string,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
@@ -142,12 +148,15 @@ export default function AdminJobDetailStatus() {
|
|||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
|
|
||||||
{data && data?.catatan && (status === "reject" || status === "review") && (
|
{data &&
|
||||||
<ReportBox text={data?.catatan}/>
|
data?.catatan &&
|
||||||
)}
|
(status === "reject" || status === "review") && (
|
||||||
|
<ReportBox text={data?.catatan} />
|
||||||
|
)}
|
||||||
|
|
||||||
{status === "review" && (
|
{status === "review" && (
|
||||||
<AdminButtonReview
|
<AdminButtonReview
|
||||||
|
isLoading={isLoading}
|
||||||
onPublish={() => {
|
onPublish={() => {
|
||||||
AlertDefaultSystem({
|
AlertDefaultSystem({
|
||||||
title: "Publish",
|
title: "Publish",
|
||||||
@@ -156,6 +165,7 @@ export default function AdminJobDetailStatus() {
|
|||||||
textRight: "Ya",
|
textRight: "Ya",
|
||||||
onPressRight: () => {
|
onPressRight: () => {
|
||||||
handleUpdate({ changeStatus: "publish" });
|
handleUpdate({ changeStatus: "publish" });
|
||||||
|
setIsLoading(true);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ import Toast from "react-native-toast-message";
|
|||||||
|
|
||||||
export default function AdminJobRejectInput() {
|
export default function AdminJobRejectInput() {
|
||||||
const { id, status } = useLocalSearchParams();
|
const { id, status } = useLocalSearchParams();
|
||||||
const [data, setData] = useState<any | null>(null);
|
const [data, setData] = useState({
|
||||||
|
catatan: "",
|
||||||
|
senderId: ""
|
||||||
|
});
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
@@ -48,7 +51,7 @@ export default function AdminJobRejectInput() {
|
|||||||
const response = await funUpdateStatusJob({
|
const response = await funUpdateStatusJob({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
changeStatus,
|
changeStatus,
|
||||||
data: data,
|
data: data ,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
@@ -102,8 +105,8 @@ export default function AdminJobRejectInput() {
|
|||||||
headerComponent={<AdminBackButtonAntTitle title="Penolakan Job" />}
|
headerComponent={<AdminBackButtonAntTitle title="Penolakan Job" />}
|
||||||
>
|
>
|
||||||
<TextAreaCustom
|
<TextAreaCustom
|
||||||
value={data}
|
value={data?.catatan}
|
||||||
onChangeText={setData}
|
onChangeText={(text) => setData({ ...data, catatan: text })}
|
||||||
placeholder="Masukan alasan"
|
placeholder="Masukan alasan"
|
||||||
required
|
required
|
||||||
showCount
|
showCount
|
||||||
|
|||||||
@@ -1,20 +1,213 @@
|
|||||||
import { BackButton, TextCustom, ViewWrapper } from "@/components";
|
import {
|
||||||
import { Stack } from "expo-router";
|
AlertDefaultSystem,
|
||||||
|
BackButton,
|
||||||
|
BaseBox,
|
||||||
|
DrawerCustom,
|
||||||
|
MenuDrawerDynamicGrid,
|
||||||
|
NewWrapper,
|
||||||
|
ScrollableCustom,
|
||||||
|
StackCustom,
|
||||||
|
TextCustom,
|
||||||
|
} from "@/components";
|
||||||
|
import { IconPlus } from "@/components/_Icon";
|
||||||
|
import { IconDot } from "@/components/_Icon/IconComponent";
|
||||||
|
import ListSkeletonComponent from "@/components/_ShareComponent/ListSkeletonComponent";
|
||||||
|
import NoDataText from "@/components/_ShareComponent/NoDataText";
|
||||||
|
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
import { useNotificationStore } from "@/hooks/use-notification-store";
|
||||||
|
import { apiGetNotificationsById } from "@/service/api-notifications";
|
||||||
|
import { listOfcategoriesAppNotification } from "@/types/type-notification-category";
|
||||||
|
import { formatChatTime } from "@/utils/formatChatTime";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { router, Stack, useFocusEffect } from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
import { RefreshControl, View } from "react-native";
|
||||||
|
|
||||||
|
const selectedCategory = (value: string) => {
|
||||||
|
const category = listOfcategoriesAppNotification.find(
|
||||||
|
(c) => c.value === value
|
||||||
|
);
|
||||||
|
return category?.label;
|
||||||
|
};
|
||||||
|
|
||||||
|
const BoxNotification = ({
|
||||||
|
data,
|
||||||
|
activeCategory,
|
||||||
|
}: {
|
||||||
|
data: any;
|
||||||
|
activeCategory: string | null;
|
||||||
|
}) => {
|
||||||
|
const { markAsRead } = useNotificationStore();
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BaseBox
|
||||||
|
backgroundColor={data.isRead ? AccentColor.darkblue : AccentColor.blue}
|
||||||
|
onPress={() => {
|
||||||
|
console.log(
|
||||||
|
"Notification >",
|
||||||
|
selectedCategory(activeCategory as string)
|
||||||
|
);
|
||||||
|
router.push(data.deepLink);
|
||||||
|
markAsRead(data.id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<StackCustom>
|
||||||
|
<TextCustom truncate={2} bold>
|
||||||
|
{data.title}
|
||||||
|
</TextCustom>
|
||||||
|
|
||||||
|
<TextCustom truncate={2}>{data.pesan}</TextCustom>
|
||||||
|
|
||||||
|
<TextCustom size="small" color="gray">
|
||||||
|
{formatChatTime(data.createdAt)}
|
||||||
|
</TextCustom>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default function AdminNotification() {
|
export default function AdminNotification() {
|
||||||
|
const { user } = useAuth();
|
||||||
|
const [activeCategory, setActiveCategory] = useState<string | null>("event");
|
||||||
|
const [listData, setListData] = useState<any[]>([]);
|
||||||
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
|
||||||
|
const { markAsReadAll } = useNotificationStore();
|
||||||
|
|
||||||
|
const handlePress = (item: any) => {
|
||||||
|
setActiveCategory(item.value);
|
||||||
|
// tambahkan logika lain seperti filter dsb.
|
||||||
|
};
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
fecthData();
|
||||||
|
}, [activeCategory])
|
||||||
|
);
|
||||||
|
|
||||||
|
const fecthData = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const response = await apiGetNotificationsById({
|
||||||
|
id: user?.id as any,
|
||||||
|
category: activeCategory as any,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
setListData(response.data);
|
||||||
|
} else {
|
||||||
|
setListData([]);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error Notification", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onRefresh = () => {
|
||||||
|
setRefreshing(true);
|
||||||
|
fecthData();
|
||||||
|
setRefreshing(false);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
options={{
|
options={{
|
||||||
title: "Admin Notifikasi",
|
title: "Admin Notifikasi",
|
||||||
headerLeft: () => <BackButton />,
|
headerLeft: () => <BackButton />,
|
||||||
headerRight: () => <></>,
|
headerRight: () => (
|
||||||
|
<IconDot
|
||||||
|
color={MainColor.yellow}
|
||||||
|
onPress={() => setOpenDrawer(true)}
|
||||||
|
/>
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ViewWrapper>
|
<NewWrapper
|
||||||
<TextCustom>Notification</TextCustom>
|
headerComponent={
|
||||||
</ViewWrapper>
|
<ScrollableCustom
|
||||||
|
data={listOfcategoriesAppNotification.map((e, i) => ({
|
||||||
|
id: i,
|
||||||
|
label: e.label,
|
||||||
|
value: e.value,
|
||||||
|
}))}
|
||||||
|
onButtonPress={handlePress}
|
||||||
|
activeId={activeCategory as string}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
refreshControl={
|
||||||
|
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<ListSkeletonComponent />
|
||||||
|
) : _.isEmpty(listData) ? (
|
||||||
|
<NoDataText text="Belum ada notifikasi" />
|
||||||
|
) : (
|
||||||
|
listData.map((e, i) => (
|
||||||
|
<View key={i}>
|
||||||
|
<BoxNotification
|
||||||
|
data={e}
|
||||||
|
activeCategory={activeCategory as any}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</NewWrapper>
|
||||||
|
|
||||||
|
<DrawerCustom
|
||||||
|
isVisible={openDrawer}
|
||||||
|
closeDrawer={() => setOpenDrawer(false)}
|
||||||
|
height={"auto"}
|
||||||
|
>
|
||||||
|
<MenuDrawerDynamicGrid
|
||||||
|
data={[
|
||||||
|
{
|
||||||
|
label: "Tandai Semua Dibaca",
|
||||||
|
value: "read-all",
|
||||||
|
icon: (
|
||||||
|
<Ionicons
|
||||||
|
name="reader-outline"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
path: "",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPressItem={(item: any) => {
|
||||||
|
console.log("Item", item.value);
|
||||||
|
if (item.value === "read-all") {
|
||||||
|
AlertDefaultSystem({
|
||||||
|
title: "Tandai Semua Dibaca",
|
||||||
|
message:
|
||||||
|
"Apakah Anda yakin ingin menandai semua notifikasi dibaca?",
|
||||||
|
textLeft: "Batal",
|
||||||
|
textRight: "Ya",
|
||||||
|
onPressRight: () => {
|
||||||
|
markAsReadAll(user?.id as any);
|
||||||
|
const data = _.cloneDeep(listData);
|
||||||
|
data.forEach((e) => {
|
||||||
|
e.isRead = true;
|
||||||
|
});
|
||||||
|
setListData(data);
|
||||||
|
onRefresh();
|
||||||
|
setOpenDrawer(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</DrawerCustom>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ export default function SuperAdminDetail() {
|
|||||||
const response = await apiAdminUserAccessUpdateStatus({
|
const response = await apiAdminUserAccessUpdateStatus({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
role: data?.masterUserRoleId === "2" ? "user" : "admin",
|
role: data?.masterUserRoleId === "2" ? "user" : "admin",
|
||||||
|
category: "role"
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
|
|||||||
@@ -9,15 +9,21 @@ import {
|
|||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import GridTwoView from "@/components/_ShareComponent/GridTwoView";
|
import GridTwoView from "@/components/_ShareComponent/GridTwoView";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
import { routeUser } from "@/lib/routeApp";
|
||||||
import {
|
import {
|
||||||
apiAdminUserAccessGetById,
|
apiAdminUserAccessGetById,
|
||||||
apiAdminUserAccessUpdateStatus,
|
apiAdminUserAccessUpdateStatus,
|
||||||
} from "@/service/api-admin/api-admin-user-access";
|
} from "@/service/api-admin/api-admin-user-access";
|
||||||
|
import {
|
||||||
|
apiNotificationsSendById
|
||||||
|
} from "@/service/api-notifications";
|
||||||
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 Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminUserAccessDetail() {
|
export default function AdminUserAccessDetail() {
|
||||||
|
const { user } = useAuth();
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
const [data, setData] = useState<any | null>(null);
|
const [data, setData] = useState<any | null>(null);
|
||||||
const [loadData, setLoadData] = useState(false);
|
const [loadData, setLoadData] = useState(false);
|
||||||
@@ -33,6 +39,7 @@ export default function AdminUserAccessDetail() {
|
|||||||
try {
|
try {
|
||||||
setLoadData(true);
|
setLoadData(true);
|
||||||
const response = await apiAdminUserAccessGetById({ id: id as string });
|
const response = await apiAdminUserAccessGetById({ id: id as string });
|
||||||
|
console.log("[DATA]", JSON.stringify(response.data, null, 2));
|
||||||
|
|
||||||
setData(response.data);
|
setData(response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -48,6 +55,7 @@ export default function AdminUserAccessDetail() {
|
|||||||
const response = await apiAdminUserAccessUpdateStatus({
|
const response = await apiAdminUserAccessUpdateStatus({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
active: !data?.active,
|
active: !data?.active,
|
||||||
|
category: "access",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
@@ -61,6 +69,21 @@ export default function AdminUserAccessDetail() {
|
|||||||
type: "success",
|
type: "success",
|
||||||
text1: "Update aktifasi berhasil ",
|
text1: "Update aktifasi berhasil ",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (data.active === false) {
|
||||||
|
await apiNotificationsSendById({
|
||||||
|
data: {
|
||||||
|
title: "Akun anda telah diaktifkan",
|
||||||
|
body: "Selamat menjelajahi HIConnect",
|
||||||
|
userLoginId: user?.id || "",
|
||||||
|
kategoriApp: "OTHER",
|
||||||
|
type: "announcement",
|
||||||
|
deepLink: routeUser.home,
|
||||||
|
},
|
||||||
|
id: id as string,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
router.back();
|
router.back();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR UPDATE STATUS]", error);
|
console.log("[ERROR UPDATE STATUS]", error);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import AdminButtonReview from "@/components/_ShareComponent/Admin/ButtonReview";
|
|||||||
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
|
||||||
import ReportBox from "@/components/Box/ReportBox";
|
import ReportBox from "@/components/Box/ReportBox";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import funUpdateStatusVoting from "@/screens/Admin/Voting/funUpdateStatus";
|
import funUpdateStatusVoting from "@/screens/Admin/Voting/funUpdateStatus";
|
||||||
import { apiAdminVotingById } from "@/service/api-admin/api-admin-voting";
|
import { apiAdminVotingById } from "@/service/api-admin/api-admin-voting";
|
||||||
import { colorBadgeStatus } from "@/utils/colorBadge";
|
import { colorBadgeStatus } from "@/utils/colorBadge";
|
||||||
@@ -29,6 +30,7 @@ import { List } from "react-native-paper";
|
|||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminVotingDetail() {
|
export default function AdminVotingDetail() {
|
||||||
|
const { user } = useAuth();
|
||||||
const { id, status } = useLocalSearchParams();
|
const { id, status } = useLocalSearchParams();
|
||||||
const [data, setData] = useState<any | null>(null);
|
const [data, setData] = useState<any | null>(null);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
@@ -139,6 +141,10 @@ export default function AdminVotingDetail() {
|
|||||||
const response = await funUpdateStatusVoting({
|
const response = await funUpdateStatusVoting({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
changeStatus,
|
changeStatus,
|
||||||
|
data: {
|
||||||
|
senderId: user?.id as string,
|
||||||
|
catatan: "",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
} from "@/components";
|
} from "@/components";
|
||||||
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
|
||||||
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import funUpdateStatusVoting from "@/screens/Admin/Voting/funUpdateStatus";
|
import funUpdateStatusVoting from "@/screens/Admin/Voting/funUpdateStatus";
|
||||||
import { apiAdminVotingById } from "@/service/api-admin/api-admin-voting";
|
import { apiAdminVotingById } from "@/service/api-admin/api-admin-voting";
|
||||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
@@ -14,6 +15,7 @@ import { useCallback, useState } from "react";
|
|||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function AdminVotingRejectInput() {
|
export default function AdminVotingRejectInput() {
|
||||||
|
const { user } = useAuth()
|
||||||
const { id, status } = useLocalSearchParams();
|
const { id, status } = useLocalSearchParams();
|
||||||
const [data, setData] = useState("");
|
const [data, setData] = useState("");
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
@@ -48,7 +50,10 @@ export default function AdminVotingRejectInput() {
|
|||||||
const response = await funUpdateStatusVoting({
|
const response = await funUpdateStatusVoting({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
changeStatus,
|
changeStatus,
|
||||||
data: data,
|
data: {
|
||||||
|
catatan: data,
|
||||||
|
senderId: user?.id as string,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
import { StackCustom, TextCustom, ViewWrapper } from "@/components";
|
import { BackButton, StackCustom, TextCustom, ViewWrapper } from "@/components";
|
||||||
|
import { Stack } from "expo-router";
|
||||||
|
|
||||||
export default function NotFoundScreen() {
|
export default function NotFoundScreen() {
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<Stack.Screen
|
||||||
|
options={{ headerShown: false, headerLeft: () => <BackButton /> }}
|
||||||
|
/>
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
<StackCustom align="center" gap={0} style={{justifyContent: "center", alignItems: "center", flex: 1}}>
|
<StackCustom
|
||||||
<TextCustom size="large" bold style={{fontSize: 100}}>
|
align="center"
|
||||||
|
gap={0}
|
||||||
|
style={{ justifyContent: "center", alignItems: "center", flex: 1 }}
|
||||||
|
>
|
||||||
|
<TextCustom size="large" bold style={{ fontSize: 100 }}>
|
||||||
404
|
404
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
<TextCustom size="large" bold>
|
<TextCustom size="large" bold>
|
||||||
@@ -12,5 +21,6 @@ export default function NotFoundScreen() {
|
|||||||
</TextCustom>
|
</TextCustom>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
);
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
9
app/eula.tsx
Normal file
9
app/eula.tsx
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import EULAView from "@/screens/Authentication/EULAView";
|
||||||
|
|
||||||
|
export default function EULA() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<EULAView />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
263
bun.lock
263
bun.lock
@@ -68,6 +68,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
"@react-native-community/cli": "^20.0.2",
|
"@react-native-community/cli": "^20.0.2",
|
||||||
|
"@react-native/metro-config": "^0.83.1",
|
||||||
"@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",
|
||||||
@@ -707,9 +708,9 @@
|
|||||||
|
|
||||||
"@react-native/assets-registry": ["@react-native/assets-registry@0.81.4", "", {}, "sha512-AMcDadefBIjD10BRqkWw+W/VdvXEomR6aEZ0fhQRAv7igrBzb4PTn4vHKYg+sUK0e3wa74kcMy2DLc/HtnGcMA=="],
|
"@react-native/assets-registry": ["@react-native/assets-registry@0.81.4", "", {}, "sha512-AMcDadefBIjD10BRqkWw+W/VdvXEomR6aEZ0fhQRAv7igrBzb4PTn4vHKYg+sUK0e3wa74kcMy2DLc/HtnGcMA=="],
|
||||||
|
|
||||||
"@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.79.5", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.79.5" } }, "sha512-Rt/imdfqXihD/sn0xnV4flxxb1aLLjPtMF1QleQjEhJsTUPpH4TFlfOpoCvsrXoDl4OIcB1k4FVM24Ez92zf5w=="],
|
"@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.83.1", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.83.1" } }, "sha512-VPj8O3pG1ESjZho9WVKxqiuryrotAECPHGF5mx46zLUYNTWR5u9OMUXYk7LeLy+JLWdGEZ2Gn3KoXeFZbuqE+g=="],
|
||||||
|
|
||||||
"@react-native/babel-preset": ["@react-native/babel-preset@0.79.5", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-arrow-functions": "^7.24.7", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-computed-properties": "^7.24.7", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-function-name": "^7.25.1", "@babel/plugin-transform-literals": "^7.25.2", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-numeric-separator": "^7.24.7", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-shorthand-properties": "^7.24.7", "@babel/plugin-transform-spread": "^7.24.7", "@babel/plugin-transform-sticky-regex": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", "@react-native/babel-plugin-codegen": "0.79.5", "babel-plugin-syntax-hermes-parser": "0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-GDUYIWslMLbdJHEgKNfrOzXk8EDKxKzbwmBXUugoiSlr6TyepVZsj3GZDLEFarOcTwH1EXXHJsixihk8DCRQDA=="],
|
"@react-native/babel-preset": ["@react-native/babel-preset@0.83.1", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-arrow-functions": "^7.24.7", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-computed-properties": "^7.24.7", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-function-name": "^7.25.1", "@babel/plugin-transform-literals": "^7.25.2", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-numeric-separator": "^7.24.7", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-shorthand-properties": "^7.24.7", "@babel/plugin-transform-spread": "^7.24.7", "@babel/plugin-transform-sticky-regex": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", "@react-native/babel-plugin-codegen": "0.83.1", "babel-plugin-syntax-hermes-parser": "0.32.0", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-xI+tbsD4fXcI6PVU4sauRCh0a5fuLQC849SINmU2J5wP8kzKu4Ye0YkGjUW3mfGrjaZcjkWmF6s33jpyd3gdTw=="],
|
||||||
|
|
||||||
"@react-native/codegen": ["@react-native/codegen@0.81.4", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.25.3", "glob": "^7.1.1", "hermes-parser": "0.29.1", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" } }, "sha512-LWTGUTzFu+qOQnvkzBP52B90Ym3stZT8IFCzzUrppz8Iwglg83FCtDZAR4yLHI29VY/x/+pkcWAMCl3739XHdw=="],
|
"@react-native/codegen": ["@react-native/codegen@0.81.4", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.25.3", "glob": "^7.1.1", "hermes-parser": "0.29.1", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" } }, "sha512-LWTGUTzFu+qOQnvkzBP52B90Ym3stZT8IFCzzUrppz8Iwglg83FCtDZAR4yLHI29VY/x/+pkcWAMCl3739XHdw=="],
|
||||||
|
|
||||||
@@ -721,7 +722,11 @@
|
|||||||
|
|
||||||
"@react-native/gradle-plugin": ["@react-native/gradle-plugin@0.81.4", "", {}, "sha512-T7fPcQvDDCSusZFVSg6H1oVDKb/NnVYLnsqkcHsAF2C2KGXyo3J7slH/tJAwNfj/7EOA2OgcWxfC1frgn9TQvw=="],
|
"@react-native/gradle-plugin": ["@react-native/gradle-plugin@0.81.4", "", {}, "sha512-T7fPcQvDDCSusZFVSg6H1oVDKb/NnVYLnsqkcHsAF2C2KGXyo3J7slH/tJAwNfj/7EOA2OgcWxfC1frgn9TQvw=="],
|
||||||
|
|
||||||
"@react-native/js-polyfills": ["@react-native/js-polyfills@0.81.4", "", {}, "sha512-sr42FaypKXJHMVHhgSbu2f/ZJfrLzgaoQ+HdpRvKEiEh2mhFf6XzZwecyLBvWqf2pMPZa+CpPfNPiejXjKEy8w=="],
|
"@react-native/js-polyfills": ["@react-native/js-polyfills@0.83.1", "", {}, "sha512-qgPpdWn/c5laA+3WoJ6Fak8uOm7CG50nBsLlPsF8kbT7rUHIVB9WaP6+GPsoKV/H15koW7jKuLRoNVT7c3Ht3w=="],
|
||||||
|
|
||||||
|
"@react-native/metro-babel-transformer": ["@react-native/metro-babel-transformer@0.83.1", "", { "dependencies": { "@babel/core": "^7.25.2", "@react-native/babel-preset": "0.83.1", "hermes-parser": "0.32.0", "nullthrows": "^1.1.1" } }, "sha512-fqt6DHWX1GBGDKa5WJOjDtPPy2M9lkYVLn59fBeFQ0GXhBRzNbUh8JzWWI/Q2CLDZ2tgKCcwaiXJ1OHWVd2BCQ=="],
|
||||||
|
|
||||||
|
"@react-native/metro-config": ["@react-native/metro-config@0.83.1", "", { "dependencies": { "@react-native/js-polyfills": "0.83.1", "@react-native/metro-babel-transformer": "0.83.1", "metro-config": "^0.83.3", "metro-runtime": "^0.83.3" } }, "sha512-1rjYZf62fCm6QAinHmRAKnJxIypX0VF/zBPd0qWvWABMZugrS0eACuIbk9Wk0StBod4yL8KnwEJyg77ak8xYzQ=="],
|
||||||
|
|
||||||
"@react-native/normalize-colors": ["@react-native/normalize-colors@0.81.4", "", {}, "sha512-9nRRHO1H+tcFqjb9gAM105Urtgcanbta2tuqCVY0NATHeFPDEAB7gPyiLxCHKMi1NbhP6TH0kxgSWXKZl1cyRg=="],
|
"@react-native/normalize-colors": ["@react-native/normalize-colors@0.81.4", "", {}, "sha512-9nRRHO1H+tcFqjb9gAM105Urtgcanbta2tuqCVY0NATHeFPDEAB7gPyiLxCHKMi1NbhP6TH0kxgSWXKZl1cyRg=="],
|
||||||
|
|
||||||
@@ -1585,9 +1590,9 @@
|
|||||||
|
|
||||||
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
|
||||||
|
|
||||||
"hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
|
"hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="],
|
||||||
|
|
||||||
"hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
"hermes-parser": ["hermes-parser@0.32.0", "", { "dependencies": { "hermes-estree": "0.32.0" } }, "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw=="],
|
||||||
|
|
||||||
"hey-listen": ["hey-listen@1.0.8", "", {}, "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="],
|
"hey-listen": ["hey-listen@1.0.8", "", {}, "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="],
|
||||||
|
|
||||||
@@ -1917,17 +1922,17 @@
|
|||||||
|
|
||||||
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
|
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
|
||||||
|
|
||||||
"metro": ["metro@0.83.1", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "@babel/types": "^7.25.2", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.29.1", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.1", "metro-cache": "0.83.1", "metro-cache-key": "0.83.1", "metro-config": "0.83.1", "metro-core": "0.83.1", "metro-file-map": "0.83.1", "metro-resolver": "0.83.1", "metro-runtime": "0.83.1", "metro-source-map": "0.83.1", "metro-symbolicate": "0.83.1", "metro-transform-plugins": "0.83.1", "metro-transform-worker": "0.83.1", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-UGKepmTxoGD4HkQV8YWvpvwef7fUujNtTgG4Ygf7m/M0qjvb9VuDmAsEU+UdriRX7F61pnVK/opz89hjKlYTXA=="],
|
"metro": ["metro@0.83.3", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "@babel/types": "^7.25.2", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.32.0", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.3", "metro-cache": "0.83.3", "metro-cache-key": "0.83.3", "metro-config": "0.83.3", "metro-core": "0.83.3", "metro-file-map": "0.83.3", "metro-resolver": "0.83.3", "metro-runtime": "0.83.3", "metro-source-map": "0.83.3", "metro-symbolicate": "0.83.3", "metro-transform-plugins": "0.83.3", "metro-transform-worker": "0.83.3", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-+rP+/GieOzkt97hSJ0MrPOuAH/jpaS21ZDvL9DJ35QYRDlQcwzcvUlGUf79AnQxq/2NPiS/AULhhM4TKutIt8Q=="],
|
||||||
|
|
||||||
"metro-babel-transformer": ["metro-babel-transformer@0.83.1", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.29.1", "nullthrows": "^1.1.1" } }, "sha512-r3xAD3964E8dwDBaZNSO2aIIvWXjIK80uO2xo0/pi3WI8XWT9h5SCjtGWtMtE5PRWw+t20TN0q1WMRsjvhC1rQ=="],
|
"metro-babel-transformer": ["metro-babel-transformer@0.83.1", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.29.1", "nullthrows": "^1.1.1" } }, "sha512-r3xAD3964E8dwDBaZNSO2aIIvWXjIK80uO2xo0/pi3WI8XWT9h5SCjtGWtMtE5PRWw+t20TN0q1WMRsjvhC1rQ=="],
|
||||||
|
|
||||||
"metro-cache": ["metro-cache@0.83.1", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.1" } }, "sha512-7N/Ad1PHa1YMWDNiyynTPq34Op2qIE68NWryGEQ4TSE3Zy6a8GpsYnEEZE4Qi6aHgsE+yZHKkRczeBgxhnFIxQ=="],
|
"metro-cache": ["metro-cache@0.83.3", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.3" } }, "sha512-3jo65X515mQJvKqK3vWRblxDEcgY55Sk3w4xa6LlfEXgQ9g1WgMh9m4qVZVwgcHoLy0a2HENTPCCX4Pk6s8c8Q=="],
|
||||||
|
|
||||||
"metro-cache-key": ["metro-cache-key@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-ZUs+GD5CNeDLxx5UUWmfg26IL+Dnbryd+TLqTlZnDEgehkIa11kUSvgF92OFfJhONeXzV4rZDRGNXoo6JT+8Gg=="],
|
"metro-cache-key": ["metro-cache-key@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-ZUs+GD5CNeDLxx5UUWmfg26IL+Dnbryd+TLqTlZnDEgehkIa11kUSvgF92OFfJhONeXzV4rZDRGNXoo6JT+8Gg=="],
|
||||||
|
|
||||||
"metro-config": ["metro-config@0.83.1", "", { "dependencies": { "connect": "^3.6.5", "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.1", "metro-cache": "0.83.1", "metro-core": "0.83.1", "metro-runtime": "0.83.1" } }, "sha512-HJhpZx3wyOkux/jeF1o7akFJzZFdbn6Zf7UQqWrvp7gqFqNulQ8Mju09raBgPmmSxKDl4LbbNeigkX0/nKY1QA=="],
|
"metro-config": ["metro-config@0.83.3", "", { "dependencies": { "connect": "^3.6.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.3", "metro-cache": "0.83.3", "metro-core": "0.83.3", "metro-runtime": "0.83.3", "yaml": "^2.6.1" } }, "sha512-mTel7ipT0yNjKILIan04bkJkuCzUUkm2SeEaTads8VfEecCh+ltXchdq6DovXJqzQAXuR2P9cxZB47Lg4klriA=="],
|
||||||
|
|
||||||
"metro-core": ["metro-core@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.1" } }, "sha512-uVL1eAJcMFd2o2Q7dsbpg8COaxjZBBGaXqO2OHnivpCdfanraVL8dPmY6It9ZeqWLOihUKZ2yHW4b6soVCzH/Q=="],
|
"metro-core": ["metro-core@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.3" } }, "sha512-M+X59lm7oBmJZamc96usuF1kusd5YimqG/q97g4Ac7slnJ3YiGglW5CsOlicTR5EWf8MQFxxjDoB6ytTqRe8Hw=="],
|
||||||
|
|
||||||
"metro-file-map": ["metro-file-map@0.83.1", "", { "dependencies": { "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-Yu429lnexKl44PttKw3nhqgmpBR+6UQ/tRaYcxPeEShtcza9DWakCn7cjqDTQZtWR2A8xSNv139izJMyQ4CG+w=="],
|
"metro-file-map": ["metro-file-map@0.83.1", "", { "dependencies": { "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-Yu429lnexKl44PttKw3nhqgmpBR+6UQ/tRaYcxPeEShtcza9DWakCn7cjqDTQZtWR2A8xSNv139izJMyQ4CG+w=="],
|
||||||
|
|
||||||
@@ -1935,7 +1940,7 @@
|
|||||||
|
|
||||||
"metro-resolver": ["metro-resolver@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-t8j46kiILAqqFS5RNa+xpQyVjULxRxlvMidqUswPEk5nQVNdlJslqizDm/Et3v/JKwOtQGkYAQCHxP1zGStR/g=="],
|
"metro-resolver": ["metro-resolver@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-t8j46kiILAqqFS5RNa+xpQyVjULxRxlvMidqUswPEk5nQVNdlJslqizDm/Et3v/JKwOtQGkYAQCHxP1zGStR/g=="],
|
||||||
|
|
||||||
"metro-runtime": ["metro-runtime@0.83.1", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-3Ag8ZS4IwafL/JUKlaeM6/CbkooY+WcVeqdNlBG0m4S0Qz0om3rdFdy1y6fYBpl6AwXJwWeMuXrvZdMuByTcRA=="],
|
"metro-runtime": ["metro-runtime@0.83.3", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw=="],
|
||||||
|
|
||||||
"metro-source-map": ["metro-source-map@0.83.1", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.1", "nullthrows": "^1.1.1", "ob1": "0.83.1", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-De7Vbeo96fFZ2cqmI0fWwVJbtHIwPZv++LYlWSwzTiCzxBDJORncN0LcT48Vi2UlQLzXJg+/CuTAcy7NBVh69A=="],
|
"metro-source-map": ["metro-source-map@0.83.1", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.1", "nullthrows": "^1.1.1", "ob1": "0.83.1", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-De7Vbeo96fFZ2cqmI0fWwVJbtHIwPZv++LYlWSwzTiCzxBDJORncN0LcT48Vi2UlQLzXJg+/CuTAcy7NBVh69A=="],
|
||||||
|
|
||||||
@@ -2717,10 +2722,22 @@
|
|||||||
|
|
||||||
"@expo/json-file/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
"@expo/json-file/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro": ["metro@0.83.1", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "@babel/types": "^7.25.2", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.29.1", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.1", "metro-cache": "0.83.1", "metro-cache-key": "0.83.1", "metro-config": "0.83.1", "metro-core": "0.83.1", "metro-file-map": "0.83.1", "metro-resolver": "0.83.1", "metro-runtime": "0.83.1", "metro-source-map": "0.83.1", "metro-symbolicate": "0.83.1", "metro-transform-plugins": "0.83.1", "metro-transform-worker": "0.83.1", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-UGKepmTxoGD4HkQV8YWvpvwef7fUujNtTgG4Ygf7m/M0qjvb9VuDmAsEU+UdriRX7F61pnVK/opz89hjKlYTXA=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro-cache": ["metro-cache@0.83.1", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.1" } }, "sha512-7N/Ad1PHa1YMWDNiyynTPq34Op2qIE68NWryGEQ4TSE3Zy6a8GpsYnEEZE4Qi6aHgsE+yZHKkRczeBgxhnFIxQ=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro-config": ["metro-config@0.83.1", "", { "dependencies": { "connect": "^3.6.5", "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.1", "metro-cache": "0.83.1", "metro-core": "0.83.1", "metro-runtime": "0.83.1" } }, "sha512-HJhpZx3wyOkux/jeF1o7akFJzZFdbn6Zf7UQqWrvp7gqFqNulQ8Mju09raBgPmmSxKDl4LbbNeigkX0/nKY1QA=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro-core": ["metro-core@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.1" } }, "sha512-uVL1eAJcMFd2o2Q7dsbpg8COaxjZBBGaXqO2OHnivpCdfanraVL8dPmY6It9ZeqWLOihUKZ2yHW4b6soVCzH/Q=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro-runtime": ["metro-runtime@0.83.1", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-3Ag8ZS4IwafL/JUKlaeM6/CbkooY+WcVeqdNlBG0m4S0Qz0om3rdFdy1y6fYBpl6AwXJwWeMuXrvZdMuByTcRA=="],
|
||||||
|
|
||||||
"@expo/metro-config/@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
|
"@expo/metro-config/@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
|
||||||
|
|
||||||
"@expo/metro-config/@expo/json-file": ["@expo/json-file@10.0.7", "", { "dependencies": { "@babel/code-frame": "~7.10.4", "json5": "^2.2.3" } }, "sha512-z2OTC0XNO6riZu98EjdNHC05l51ySeTto6GP7oSQrCvQgG9ARBwD1YvMQaVZ9wU7p/4LzSf1O7tckL3B45fPpw=="],
|
"@expo/metro-config/@expo/json-file": ["@expo/json-file@10.0.7", "", { "dependencies": { "@babel/code-frame": "~7.10.4", "json5": "^2.2.3" } }, "sha512-z2OTC0XNO6riZu98EjdNHC05l51ySeTto6GP7oSQrCvQgG9ARBwD1YvMQaVZ9wU7p/4LzSf1O7tckL3B45fPpw=="],
|
||||||
|
|
||||||
|
"@expo/metro-config/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
||||||
|
|
||||||
"@expo/metro-config/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
"@expo/metro-config/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||||
|
|
||||||
"@expo/npm-proofread/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
|
"@expo/npm-proofread/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="],
|
||||||
@@ -2785,28 +2802,24 @@
|
|||||||
|
|
||||||
"@react-native-community/cli-tools/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
"@react-native-community/cli-tools/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||||
|
|
||||||
"@react-native/babel-plugin-codegen/@react-native/codegen": ["@react-native/codegen@0.79.5", "", { "dependencies": { "glob": "^7.1.1", "hermes-parser": "0.25.1", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" }, "peerDependencies": { "@babel/core": "*" } }, "sha512-FO5U1R525A1IFpJjy+KVznEinAgcs3u7IbnbRJUG9IH/MBXi2lEU2LtN+JarJ81MCfW4V2p0pg6t/3RGHFRrlQ=="],
|
"@react-native/babel-plugin-codegen/@babel/traverse": ["@babel/traverse@7.28.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", "@babel/types": "^7.28.2", "debug": "^4.3.1" } }, "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ=="],
|
||||||
|
|
||||||
"@react-native/babel-preset/@babel/plugin-transform-async-generator-functions": ["@babel/plugin-transform-async-generator-functions@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-remap-async-to-generator": "^7.27.1", "@babel/traverse": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA=="],
|
"@react-native/babel-plugin-codegen/@react-native/codegen": ["@react-native/codegen@0.83.1", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.25.3", "glob": "^7.1.1", "hermes-parser": "0.32.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" } }, "sha512-FpRxenonwH+c2a5X5DZMKUD7sCudHxB3eSQPgV9R+uxd28QWslyAWrpnJM/Az96AEksHnymDzEmzq2HLX5nb+g=="],
|
||||||
|
|
||||||
"@react-native/babel-preset/@babel/plugin-transform-block-scoping": ["@babel/plugin-transform-block-scoping@7.27.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-JF6uE2s67f0y2RZcm2kpAUEbD50vH62TyWVebxwHAlbSdM49VqPz8t4a1uIjp4NIOIZ4xzLfjY5emt/RCyC7TQ=="],
|
"@react-native/babel-preset/babel-plugin-syntax-hermes-parser": ["babel-plugin-syntax-hermes-parser@0.32.0", "", { "dependencies": { "hermes-parser": "0.32.0" } }, "sha512-m5HthL++AbyeEA2FcdwOLfVFvWYECOBObLHNqdR8ceY4TsEdn4LdX2oTvbB2QJSSElE2AWA/b2MXZ/PF/CqLZg=="],
|
||||||
|
|
||||||
"@react-native/babel-preset/@babel/plugin-transform-classes": ["@babel/plugin-transform-classes@7.27.1", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-compilation-targets": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/traverse": "^7.27.1", "globals": "^11.1.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA=="],
|
|
||||||
|
|
||||||
"@react-native/babel-preset/@babel/plugin-transform-destructuring": ["@babel/plugin-transform-destructuring@7.27.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-s4Jrok82JpiaIprtY2nHsYmrThKvvwgHwjgd7UMiYhZaN0asdXNLr0y+NjTfkA7SyQE5i2Fb7eawUOZmLvyqOA=="],
|
|
||||||
|
|
||||||
"@react-native/babel-preset/@babel/plugin-transform-object-rest-spread": ["@babel/plugin-transform-object-rest-spread@7.27.3", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-plugin-utils": "^7.27.1", "@babel/plugin-transform-destructuring": "^7.27.3", "@babel/plugin-transform-parameters": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-7ZZtznF9g4l2JCImCo5LNKFHB5eXnN39lLtLY5Tg+VkR0jwOt7TBciMckuiQIOIW7L5tkQOCh3bVGYeXgMx52Q=="],
|
|
||||||
|
|
||||||
"@react-native/babel-preset/@babel/plugin-transform-parameters": ["@babel/plugin-transform-parameters@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg=="],
|
|
||||||
|
|
||||||
"@react-native/babel-preset/@babel/plugin-transform-regenerator": ["@babel/plugin-transform-regenerator@7.27.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-uhB8yHerfe3MWnuLAhEbeQ4afVoqv8BQsPqrTv7e/jZ9y00kJL6l9a/f4OWaKxotmjzewfEyXE1vgDJenkQ2/Q=="],
|
|
||||||
|
|
||||||
"@react-native/babel-preset/babel-plugin-syntax-hermes-parser": ["babel-plugin-syntax-hermes-parser@0.25.1", "", { "dependencies": { "hermes-parser": "0.25.1" } }, "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ=="],
|
|
||||||
|
|
||||||
"@react-native/codegen/@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="],
|
"@react-native/codegen/@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="],
|
||||||
|
|
||||||
"@react-native/codegen/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
"@react-native/codegen/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||||
|
|
||||||
|
"@react-native/codegen/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro": ["metro@0.83.1", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "@babel/types": "^7.25.2", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.29.1", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.1", "metro-cache": "0.83.1", "metro-cache-key": "0.83.1", "metro-config": "0.83.1", "metro-core": "0.83.1", "metro-file-map": "0.83.1", "metro-resolver": "0.83.1", "metro-runtime": "0.83.1", "metro-source-map": "0.83.1", "metro-symbolicate": "0.83.1", "metro-transform-plugins": "0.83.1", "metro-transform-worker": "0.83.1", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-UGKepmTxoGD4HkQV8YWvpvwef7fUujNtTgG4Ygf7m/M0qjvb9VuDmAsEU+UdriRX7F61pnVK/opz89hjKlYTXA=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro-config": ["metro-config@0.83.1", "", { "dependencies": { "connect": "^3.6.5", "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.1", "metro-cache": "0.83.1", "metro-core": "0.83.1", "metro-runtime": "0.83.1" } }, "sha512-HJhpZx3wyOkux/jeF1o7akFJzZFdbn6Zf7UQqWrvp7gqFqNulQ8Mju09raBgPmmSxKDl4LbbNeigkX0/nKY1QA=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro-core": ["metro-core@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.1" } }, "sha512-uVL1eAJcMFd2o2Q7dsbpg8COaxjZBBGaXqO2OHnivpCdfanraVL8dPmY6It9ZeqWLOihUKZ2yHW4b6soVCzH/Q=="],
|
||||||
|
|
||||||
"@react-native/community-cli-plugin/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
"@react-native/community-cli-plugin/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||||
|
|
||||||
"@react-native/dev-middleware/open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="],
|
"@react-native/dev-middleware/open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="],
|
||||||
@@ -2849,10 +2862,14 @@
|
|||||||
|
|
||||||
"babel-plugin-react-compiler/@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
"babel-plugin-react-compiler/@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
||||||
|
|
||||||
|
"babel-plugin-syntax-hermes-parser/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
||||||
|
|
||||||
"babel-preset-expo/@babel/plugin-transform-object-rest-spread": ["@babel/plugin-transform-object-rest-spread@7.27.3", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-plugin-utils": "^7.27.1", "@babel/plugin-transform-destructuring": "^7.27.3", "@babel/plugin-transform-parameters": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-7ZZtznF9g4l2JCImCo5LNKFHB5eXnN39lLtLY5Tg+VkR0jwOt7TBciMckuiQIOIW7L5tkQOCh3bVGYeXgMx52Q=="],
|
"babel-preset-expo/@babel/plugin-transform-object-rest-spread": ["@babel/plugin-transform-object-rest-spread@7.27.3", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-plugin-utils": "^7.27.1", "@babel/plugin-transform-destructuring": "^7.27.3", "@babel/plugin-transform-parameters": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-7ZZtznF9g4l2JCImCo5LNKFHB5eXnN39lLtLY5Tg+VkR0jwOt7TBciMckuiQIOIW7L5tkQOCh3bVGYeXgMx52Q=="],
|
||||||
|
|
||||||
"babel-preset-expo/@babel/plugin-transform-parameters": ["@babel/plugin-transform-parameters@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg=="],
|
"babel-preset-expo/@babel/plugin-transform-parameters": ["@babel/plugin-transform-parameters@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg=="],
|
||||||
|
|
||||||
|
"babel-preset-expo/@react-native/babel-preset": ["@react-native/babel-preset@0.79.5", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-arrow-functions": "^7.24.7", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-computed-properties": "^7.24.7", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-function-name": "^7.25.1", "@babel/plugin-transform-literals": "^7.25.2", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-numeric-separator": "^7.24.7", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-shorthand-properties": "^7.24.7", "@babel/plugin-transform-spread": "^7.24.7", "@babel/plugin-transform-sticky-regex": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", "@react-native/babel-plugin-codegen": "0.79.5", "babel-plugin-syntax-hermes-parser": "0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-GDUYIWslMLbdJHEgKNfrOzXk8EDKxKzbwmBXUugoiSlr6TyepVZsj3GZDLEFarOcTwH1EXXHJsixihk8DCRQDA=="],
|
||||||
|
|
||||||
"babel-preset-expo/babel-plugin-syntax-hermes-parser": ["babel-plugin-syntax-hermes-parser@0.25.1", "", { "dependencies": { "hermes-parser": "0.25.1" } }, "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ=="],
|
"babel-preset-expo/babel-plugin-syntax-hermes-parser": ["babel-plugin-syntax-hermes-parser@0.25.1", "", { "dependencies": { "hermes-parser": "0.25.1" } }, "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ=="],
|
||||||
|
|
||||||
"better-opn/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="],
|
"better-opn/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="],
|
||||||
@@ -3039,9 +3056,27 @@
|
|||||||
|
|
||||||
"metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="],
|
"metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="],
|
||||||
|
|
||||||
|
"metro/metro-babel-transformer": ["metro-babel-transformer@0.83.3", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.32.0", "nullthrows": "^1.1.1" } }, "sha512-1vxlvj2yY24ES1O5RsSIvg4a4WeL7PFXgKOHvXTXiW0deLvQr28ExXj6LjwCCDZ4YZLhq6HddLpZnX4dEdSq5g=="],
|
||||||
|
|
||||||
|
"metro/metro-cache-key": ["metro-cache-key@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-59ZO049jKzSmvBmG/B5bZ6/dztP0ilp0o988nc6dpaDsU05Cl1c/lRf+yx8m9WW/JVgbmfO5MziBU559XjI5Zw=="],
|
||||||
|
|
||||||
|
"metro/metro-file-map": ["metro-file-map@0.83.3", "", { "dependencies": { "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-jg5AcyE0Q9Xbbu/4NAwwZkmQn7doJCKGW0SLeSJmzNB9Z24jBe0AL2PHNMy4eu0JiKtNWHz9IiONGZWq7hjVTA=="],
|
||||||
|
|
||||||
|
"metro/metro-resolver": ["metro-resolver@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-0js+zwI5flFxb1ktmR///bxHYg7OLpRpWZlBBruYG8OKYxeMP7SV0xQ/o/hUelrEMdK4LJzqVtHAhBm25LVfAQ=="],
|
||||||
|
|
||||||
|
"metro/metro-source-map": ["metro-source-map@0.83.3", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.3", "nullthrows": "^1.1.1", "ob1": "0.83.3", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-xkC3qwUBh2psVZgVavo8+r2C9Igkk3DibiOXSAht1aYRRcztEZNFtAMtfSB7sdO2iFMx2Mlyu++cBxz/fhdzQg=="],
|
||||||
|
|
||||||
|
"metro/metro-symbolicate": ["metro-symbolicate@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.83.3", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-F/YChgKd6KbFK3eUR5HdUsfBqVsanf5lNTwFd4Ca7uuxnHgBC3kR/Hba/RGkenR3pZaGNp5Bu9ZqqP52Wyhomw=="],
|
||||||
|
|
||||||
|
"metro/metro-transform-plugins": ["metro-transform-plugins@0.83.3", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-eRGoKJU6jmqOakBMH5kUB7VitEWiNrDzBHpYbkBXW7C5fUGeOd2CyqrosEzbMK5VMiZYyOcNFEphvxk3OXey2A=="],
|
||||||
|
|
||||||
|
"metro/metro-transform-worker": ["metro-transform-worker@0.83.3", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "metro": "0.83.3", "metro-babel-transformer": "0.83.3", "metro-cache": "0.83.3", "metro-cache-key": "0.83.3", "metro-minify-terser": "0.83.3", "metro-source-map": "0.83.3", "metro-transform-plugins": "0.83.3", "nullthrows": "^1.1.1" } }, "sha512-Ztekew9t/gOIMZX1tvJOgX7KlSLL5kWykl0Iwu2cL2vKMKVALRl1hysyhUw0vjpAvLFx+Kfq9VLjnHIkW32fPA=="],
|
||||||
|
|
||||||
"metro/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
|
"metro/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
|
||||||
|
|
||||||
"metro-config/cosmiconfig": ["cosmiconfig@5.2.1", "", { "dependencies": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" } }, "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA=="],
|
"metro-babel-transformer/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
||||||
|
|
||||||
|
"metro-core/metro-resolver": ["metro-resolver@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-0js+zwI5flFxb1ktmR///bxHYg7OLpRpWZlBBruYG8OKYxeMP7SV0xQ/o/hUelrEMdK4LJzqVtHAhBm25LVfAQ=="],
|
||||||
|
|
||||||
"metro-source-map/@babel/traverse": ["@babel/traverse@7.28.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", "@babel/types": "^7.28.2", "debug": "^4.3.1" } }, "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ=="],
|
"metro-source-map/@babel/traverse": ["@babel/traverse@7.28.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", "@babel/types": "^7.28.2", "debug": "^4.3.1" } }, "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ=="],
|
||||||
|
|
||||||
@@ -3057,6 +3092,10 @@
|
|||||||
|
|
||||||
"metro-transform-worker/@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
"metro-transform-worker/@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro": ["metro@0.83.1", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "@babel/types": "^7.25.2", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.29.1", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.1", "metro-cache": "0.83.1", "metro-cache-key": "0.83.1", "metro-config": "0.83.1", "metro-core": "0.83.1", "metro-file-map": "0.83.1", "metro-resolver": "0.83.1", "metro-runtime": "0.83.1", "metro-source-map": "0.83.1", "metro-symbolicate": "0.83.1", "metro-transform-plugins": "0.83.1", "metro-transform-worker": "0.83.1", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-UGKepmTxoGD4HkQV8YWvpvwef7fUujNtTgG4Ygf7m/M0qjvb9VuDmAsEU+UdriRX7F61pnVK/opz89hjKlYTXA=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro-cache": ["metro-cache@0.83.1", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.1" } }, "sha512-7N/Ad1PHa1YMWDNiyynTPq34Op2qIE68NWryGEQ4TSE3Zy6a8GpsYnEEZE4Qi6aHgsE+yZHKkRczeBgxhnFIxQ=="],
|
||||||
|
|
||||||
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||||
|
|
||||||
"node-fetch/whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
|
"node-fetch/whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
|
||||||
@@ -3085,10 +3124,14 @@
|
|||||||
|
|
||||||
"react-devtools-core/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
|
"react-devtools-core/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
|
||||||
|
|
||||||
|
"react-native/@react-native/js-polyfills": ["@react-native/js-polyfills@0.81.4", "", {}, "sha512-sr42FaypKXJHMVHhgSbu2f/ZJfrLzgaoQ+HdpRvKEiEh2mhFf6XzZwecyLBvWqf2pMPZa+CpPfNPiejXjKEy8w=="],
|
||||||
|
|
||||||
"react-native/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="],
|
"react-native/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="],
|
||||||
|
|
||||||
"react-native/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
"react-native/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||||
|
|
||||||
|
"react-native/metro-runtime": ["metro-runtime@0.83.1", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-3Ag8ZS4IwafL/JUKlaeM6/CbkooY+WcVeqdNlBG0m4S0Qz0om3rdFdy1y6fYBpl6AwXJwWeMuXrvZdMuByTcRA=="],
|
||||||
|
|
||||||
"react-native/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
"react-native/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||||
|
|
||||||
"react-native-paper/color": ["color@3.2.1", "", { "dependencies": { "color-convert": "^1.9.3", "color-string": "^1.6.0" } }, "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA=="],
|
"react-native-paper/color": ["color@3.2.1", "", { "dependencies": { "color-convert": "^1.9.3", "color-string": "^1.6.0" } }, "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA=="],
|
||||||
@@ -3265,8 +3308,26 @@
|
|||||||
|
|
||||||
"@expo/metro-config/@expo/json-file/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
"@expo/metro-config/@expo/json-file/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
||||||
|
|
||||||
|
"@expo/metro-config/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
|
||||||
|
|
||||||
"@expo/metro-config/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
"@expo/metro-config/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro/@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro/@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro/@babel/traverse": ["@babel/traverse@7.28.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", "@babel/types": "^7.28.2", "debug": "^4.3.1" } }, "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro/@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro-config/cosmiconfig": ["cosmiconfig@5.2.1", "", { "dependencies": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" } }, "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA=="],
|
||||||
|
|
||||||
"@expo/package-manager/@expo/json-file/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
"@expo/package-manager/@expo/json-file/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
|
||||||
|
|
||||||
"@expo/package-manager/ora/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
"@expo/package-manager/ora/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
||||||
@@ -3295,16 +3356,44 @@
|
|||||||
|
|
||||||
"@jest/reporters/string-length/char-regex": ["char-regex@1.0.2", "", {}, "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="],
|
"@jest/reporters/string-length/char-regex": ["char-regex@1.0.2", "", {}, "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="],
|
||||||
|
|
||||||
|
"@react-native/babel-plugin-codegen/@babel/traverse/@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
|
||||||
|
|
||||||
|
"@react-native/babel-plugin-codegen/@babel/traverse/@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="],
|
||||||
|
|
||||||
|
"@react-native/babel-plugin-codegen/@babel/traverse/@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
||||||
|
|
||||||
|
"@react-native/babel-plugin-codegen/@react-native/codegen/@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="],
|
||||||
|
|
||||||
"@react-native/babel-plugin-codegen/@react-native/codegen/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
"@react-native/babel-plugin-codegen/@react-native/codegen/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||||
|
|
||||||
"@react-native/babel-plugin-codegen/@react-native/codegen/hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="],
|
|
||||||
|
|
||||||
"@react-native/babel-preset/@babel/plugin-transform-classes/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
|
|
||||||
|
|
||||||
"@react-native/babel-preset/babel-plugin-syntax-hermes-parser/hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="],
|
|
||||||
|
|
||||||
"@react-native/codegen/@babel/parser/@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
"@react-native/codegen/@babel/parser/@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
||||||
|
|
||||||
|
"@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro/@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro/@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro/@babel/traverse": ["@babel/traverse@7.28.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", "@babel/types": "^7.28.2", "debug": "^4.3.1" } }, "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro/@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro/metro-cache": ["metro-cache@0.83.1", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.1" } }, "sha512-7N/Ad1PHa1YMWDNiyynTPq34Op2qIE68NWryGEQ4TSE3Zy6a8GpsYnEEZE4Qi6aHgsE+yZHKkRczeBgxhnFIxQ=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro/metro-runtime": ["metro-runtime@0.83.1", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-3Ag8ZS4IwafL/JUKlaeM6/CbkooY+WcVeqdNlBG0m4S0Qz0om3rdFdy1y6fYBpl6AwXJwWeMuXrvZdMuByTcRA=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro-config/cosmiconfig": ["cosmiconfig@5.2.1", "", { "dependencies": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" } }, "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro-config/metro-cache": ["metro-cache@0.83.1", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.1" } }, "sha512-7N/Ad1PHa1YMWDNiyynTPq34Op2qIE68NWryGEQ4TSE3Zy6a8GpsYnEEZE4Qi6aHgsE+yZHKkRczeBgxhnFIxQ=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro-config/metro-runtime": ["metro-runtime@0.83.1", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-3Ag8ZS4IwafL/JUKlaeM6/CbkooY+WcVeqdNlBG0m4S0Qz0om3rdFdy1y6fYBpl6AwXJwWeMuXrvZdMuByTcRA=="],
|
||||||
|
|
||||||
"@react-native/dev-middleware/open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="],
|
"@react-native/dev-middleware/open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="],
|
||||||
|
|
||||||
"@testing-library/react-native/pretty-format/@jest/schemas": ["@jest/schemas@30.0.5", "", { "dependencies": { "@sinclair/typebox": "^0.34.0" } }, "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA=="],
|
"@testing-library/react-native/pretty-format/@jest/schemas": ["@jest/schemas@30.0.5", "", { "dependencies": { "@sinclair/typebox": "^0.34.0" } }, "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA=="],
|
||||||
@@ -3321,8 +3410,22 @@
|
|||||||
|
|
||||||
"ansi-fragments/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
|
"ansi-fragments/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
|
||||||
|
|
||||||
|
"babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
|
||||||
|
|
||||||
"babel-preset-expo/@babel/plugin-transform-object-rest-spread/@babel/plugin-transform-destructuring": ["@babel/plugin-transform-destructuring@7.27.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-s4Jrok82JpiaIprtY2nHsYmrThKvvwgHwjgd7UMiYhZaN0asdXNLr0y+NjTfkA7SyQE5i2Fb7eawUOZmLvyqOA=="],
|
"babel-preset-expo/@babel/plugin-transform-object-rest-spread/@babel/plugin-transform-destructuring": ["@babel/plugin-transform-destructuring@7.27.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-s4Jrok82JpiaIprtY2nHsYmrThKvvwgHwjgd7UMiYhZaN0asdXNLr0y+NjTfkA7SyQE5i2Fb7eawUOZmLvyqOA=="],
|
||||||
|
|
||||||
|
"babel-preset-expo/@react-native/babel-preset/@babel/plugin-transform-async-generator-functions": ["@babel/plugin-transform-async-generator-functions@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-remap-async-to-generator": "^7.27.1", "@babel/traverse": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA=="],
|
||||||
|
|
||||||
|
"babel-preset-expo/@react-native/babel-preset/@babel/plugin-transform-block-scoping": ["@babel/plugin-transform-block-scoping@7.27.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-JF6uE2s67f0y2RZcm2kpAUEbD50vH62TyWVebxwHAlbSdM49VqPz8t4a1uIjp4NIOIZ4xzLfjY5emt/RCyC7TQ=="],
|
||||||
|
|
||||||
|
"babel-preset-expo/@react-native/babel-preset/@babel/plugin-transform-classes": ["@babel/plugin-transform-classes@7.27.1", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-compilation-targets": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/traverse": "^7.27.1", "globals": "^11.1.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA=="],
|
||||||
|
|
||||||
|
"babel-preset-expo/@react-native/babel-preset/@babel/plugin-transform-destructuring": ["@babel/plugin-transform-destructuring@7.27.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-s4Jrok82JpiaIprtY2nHsYmrThKvvwgHwjgd7UMiYhZaN0asdXNLr0y+NjTfkA7SyQE5i2Fb7eawUOZmLvyqOA=="],
|
||||||
|
|
||||||
|
"babel-preset-expo/@react-native/babel-preset/@babel/plugin-transform-regenerator": ["@babel/plugin-transform-regenerator@7.27.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-uhB8yHerfe3MWnuLAhEbeQ4afVoqv8BQsPqrTv7e/jZ9y00kJL6l9a/f4OWaKxotmjzewfEyXE1vgDJenkQ2/Q=="],
|
||||||
|
|
||||||
|
"babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.79.5", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.79.5" } }, "sha512-Rt/imdfqXihD/sn0xnV4flxxb1aLLjPtMF1QleQjEhJsTUPpH4TFlfOpoCvsrXoDl4OIcB1k4FVM24Ez92zf5w=="],
|
||||||
|
|
||||||
"babel-preset-expo/babel-plugin-syntax-hermes-parser/hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="],
|
"babel-preset-expo/babel-plugin-syntax-hermes-parser/hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="],
|
||||||
|
|
||||||
"better-opn/open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="],
|
"better-opn/open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="],
|
||||||
@@ -3405,11 +3508,7 @@
|
|||||||
|
|
||||||
"logkitty/yargs/yargs-parser": ["yargs-parser@18.1.3", "", { "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } }, "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ=="],
|
"logkitty/yargs/yargs-parser": ["yargs-parser@18.1.3", "", { "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } }, "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ=="],
|
||||||
|
|
||||||
"metro-config/cosmiconfig/import-fresh": ["import-fresh@2.0.0", "", { "dependencies": { "caller-path": "^2.0.0", "resolve-from": "^3.0.0" } }, "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg=="],
|
"metro-babel-transformer/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
|
||||||
|
|
||||||
"metro-config/cosmiconfig/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": "bin/js-yaml.js" }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
|
|
||||||
|
|
||||||
"metro-config/cosmiconfig/parse-json": ["parse-json@4.0.0", "", { "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw=="],
|
|
||||||
|
|
||||||
"metro-source-map/@babel/traverse/@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
|
"metro-source-map/@babel/traverse/@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
|
||||||
|
|
||||||
@@ -3431,10 +3530,30 @@
|
|||||||
|
|
||||||
"metro-transform-worker/@babel/generator/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
|
"metro-transform-worker/@babel/generator/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro/@babel/traverse": ["@babel/traverse@7.28.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", "@babel/types": "^7.28.2", "debug": "^4.3.1" } }, "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro/metro-config": ["metro-config@0.83.1", "", { "dependencies": { "connect": "^3.6.5", "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.1", "metro-cache": "0.83.1", "metro-core": "0.83.1", "metro-runtime": "0.83.1" } }, "sha512-HJhpZx3wyOkux/jeF1o7akFJzZFdbn6Zf7UQqWrvp7gqFqNulQ8Mju09raBgPmmSxKDl4LbbNeigkX0/nKY1QA=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro/metro-core": ["metro-core@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.1" } }, "sha512-uVL1eAJcMFd2o2Q7dsbpg8COaxjZBBGaXqO2OHnivpCdfanraVL8dPmY6It9ZeqWLOihUKZ2yHW4b6soVCzH/Q=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro/metro-runtime": ["metro-runtime@0.83.1", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-3Ag8ZS4IwafL/JUKlaeM6/CbkooY+WcVeqdNlBG0m4S0Qz0om3rdFdy1y6fYBpl6AwXJwWeMuXrvZdMuByTcRA=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro-cache/metro-core": ["metro-core@0.83.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.1" } }, "sha512-uVL1eAJcMFd2o2Q7dsbpg8COaxjZBBGaXqO2OHnivpCdfanraVL8dPmY6It9ZeqWLOihUKZ2yHW4b6soVCzH/Q=="],
|
||||||
|
|
||||||
"metro/@babel/generator/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
"metro/@babel/generator/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||||
|
|
||||||
"metro/@babel/generator/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
|
"metro/@babel/generator/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
|
||||||
|
|
||||||
|
"metro/metro-source-map/ob1": ["ob1@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA=="],
|
||||||
|
|
||||||
|
"metro/metro-transform-worker/metro-minify-terser": ["metro-minify-terser@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-O2BmfWj6FSfzBLrNCXt/rr2VYZdX5i6444QJU0fFoc7Ljg+Q+iqebwE3K0eTvkI6TRjELsXk1cjU+fXwAR4OjQ=="],
|
||||||
|
|
||||||
"node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
|
"node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
|
||||||
|
|
||||||
"node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
|
"node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
|
||||||
@@ -3529,6 +3648,18 @@
|
|||||||
|
|
||||||
"@expo/cli/ora/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
|
"@expo/cli/ora/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro-config/cosmiconfig/import-fresh": ["import-fresh@2.0.0", "", { "dependencies": { "caller-path": "^2.0.0", "resolve-from": "^3.0.0" } }, "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro-config/cosmiconfig/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": "bin/js-yaml.js" }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro-config/cosmiconfig/parse-json": ["parse-json@4.0.0", "", { "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro/@babel/generator/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro/@babel/generator/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
|
||||||
|
|
||||||
"@expo/package-manager/ora/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
"@expo/package-manager/ora/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
||||||
|
|
||||||
"@expo/package-manager/ora/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
"@expo/package-manager/ora/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
||||||
@@ -3543,12 +3674,30 @@
|
|||||||
|
|
||||||
"@jest/reporters/istanbul-lib-instrument/@babel/parser/@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
"@jest/reporters/istanbul-lib-instrument/@babel/parser/@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
||||||
|
|
||||||
"@react-native/babel-plugin-codegen/@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="],
|
"@react-native/babel-plugin-codegen/@babel/traverse/@babel/generator/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||||
|
|
||||||
"@react-native/babel-preset/babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="],
|
"@react-native/babel-plugin-codegen/@babel/traverse/@babel/generator/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
|
||||||
|
|
||||||
|
"@react-native/babel-plugin-codegen/@react-native/codegen/@babel/parser/@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro-config/cosmiconfig/import-fresh": ["import-fresh@2.0.0", "", { "dependencies": { "caller-path": "^2.0.0", "resolve-from": "^3.0.0" } }, "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro-config/cosmiconfig/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": "bin/js-yaml.js" }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro-config/cosmiconfig/parse-json": ["parse-json@4.0.0", "", { "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro/@babel/generator/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro/@babel/generator/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
|
||||||
|
|
||||||
"@testing-library/react-native/pretty-format/@jest/schemas/@sinclair/typebox": ["@sinclair/typebox@0.34.40", "", {}, "sha512-gwBNIP8ZAYev/ORDWW0QvxdwPXwxBtLsdsJgSc7eDIRt8ubP+rxUBzPsrwnu16fgEF8Bx4lh/+mvQvJzcTM6Kw=="],
|
"@testing-library/react-native/pretty-format/@jest/schemas/@sinclair/typebox": ["@sinclair/typebox@0.34.40", "", {}, "sha512-gwBNIP8ZAYev/ORDWW0QvxdwPXwxBtLsdsJgSc7eDIRt8ubP+rxUBzPsrwnu16fgEF8Bx4lh/+mvQvJzcTM6Kw=="],
|
||||||
|
|
||||||
|
"babel-preset-expo/@react-native/babel-preset/@babel/plugin-transform-classes/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
|
||||||
|
|
||||||
|
"babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen": ["@react-native/codegen@0.79.5", "", { "dependencies": { "glob": "^7.1.1", "hermes-parser": "0.25.1", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" }, "peerDependencies": { "@babel/core": "*" } }, "sha512-FO5U1R525A1IFpJjy+KVznEinAgcs3u7IbnbRJUG9IH/MBXi2lEU2LtN+JarJ81MCfW4V2p0pg6t/3RGHFRrlQ=="],
|
||||||
|
|
||||||
"babel-preset-expo/babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="],
|
"babel-preset-expo/babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="],
|
||||||
|
|
||||||
"expo-constants/@expo/config/@expo/config-plugins/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
"expo-constants/@expo/config/@expo/config-plugins/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
|
||||||
@@ -3575,14 +3724,14 @@
|
|||||||
|
|
||||||
"logkitty/yargs/yargs-parser/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="],
|
"logkitty/yargs/yargs-parser/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="],
|
||||||
|
|
||||||
"metro-config/cosmiconfig/import-fresh/resolve-from": ["resolve-from@3.0.0", "", {}, "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw=="],
|
|
||||||
|
|
||||||
"metro-config/cosmiconfig/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
|
|
||||||
|
|
||||||
"metro-source-map/@babel/traverse/@babel/generator/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
"metro-source-map/@babel/traverse/@babel/generator/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||||
|
|
||||||
"metro-source-map/@babel/traverse/@babel/generator/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
|
"metro-source-map/@babel/traverse/@babel/generator/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro/metro-config/cosmiconfig": ["cosmiconfig@5.2.1", "", { "dependencies": { "import-fresh": "^2.0.0", "is-directory": "^0.3.1", "js-yaml": "^3.13.1", "parse-json": "^4.0.0" } }, "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA=="],
|
||||||
|
|
||||||
"pkg-dir/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
"pkg-dir/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
||||||
|
|
||||||
"qrcode/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
"qrcode/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||||
@@ -3613,6 +3762,10 @@
|
|||||||
|
|
||||||
"@expo/cli/ora/cli-cursor/restore-cursor/onetime": ["onetime@2.0.1", "", { "dependencies": { "mimic-fn": "^1.0.0" } }, "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ=="],
|
"@expo/cli/ora/cli-cursor/restore-cursor/onetime": ["onetime@2.0.1", "", { "dependencies": { "mimic-fn": "^1.0.0" } }, "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro-config/cosmiconfig/import-fresh/resolve-from": ["resolve-from@3.0.0", "", {}, "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw=="],
|
||||||
|
|
||||||
|
"@expo/metro/metro-config/cosmiconfig/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
|
||||||
|
|
||||||
"@expo/package-manager/ora/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
"@expo/package-manager/ora/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||||
|
|
||||||
"@expo/package-manager/ora/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
"@expo/package-manager/ora/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
||||||
@@ -3621,12 +3774,28 @@
|
|||||||
|
|
||||||
"@istanbuljs/load-nyc-config/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
"@istanbuljs/load-nyc-config/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro-config/cosmiconfig/import-fresh/resolve-from": ["resolve-from@3.0.0", "", {}, "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw=="],
|
||||||
|
|
||||||
|
"@react-native/community-cli-plugin/metro-config/cosmiconfig/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
|
||||||
|
|
||||||
|
"babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||||
|
|
||||||
|
"babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen/hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="],
|
||||||
|
|
||||||
"expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@babel/traverse": ["@babel/traverse@7.28.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", "@babel/types": "^7.28.2", "debug": "^4.3.1" } }, "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ=="],
|
"expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@babel/traverse": ["@babel/traverse@7.28.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", "@babel/types": "^7.28.2", "debug": "^4.3.1" } }, "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ=="],
|
||||||
|
|
||||||
|
"expo/babel-preset-expo/@react-native/babel-preset/babel-plugin-syntax-hermes-parser/hermes-parser": ["hermes-parser@0.29.1", "", { "dependencies": { "hermes-estree": "0.29.1" } }, "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA=="],
|
||||||
|
|
||||||
"expo/babel-preset-expo/babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="],
|
"expo/babel-preset-expo/babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="],
|
||||||
|
|
||||||
"logkitty/yargs/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
"logkitty/yargs/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro/metro-config/cosmiconfig/import-fresh": ["import-fresh@2.0.0", "", { "dependencies": { "caller-path": "^2.0.0", "resolve-from": "^3.0.0" } }, "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro/metro-config/cosmiconfig/js-yaml": ["js-yaml@3.14.1", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": "bin/js-yaml.js" }, "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro/metro-config/cosmiconfig/parse-json": ["parse-json@4.0.0", "", { "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw=="],
|
||||||
|
|
||||||
"pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
"pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
||||||
|
|
||||||
"qrcode/yargs/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
"qrcode/yargs/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
||||||
@@ -3639,14 +3808,22 @@
|
|||||||
|
|
||||||
"@expo/package-manager/ora/cli-cursor/restore-cursor/onetime/mimic-fn": ["mimic-fn@1.2.0", "", {}, "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="],
|
"@expo/package-manager/ora/cli-cursor/restore-cursor/onetime/mimic-fn": ["mimic-fn@1.2.0", "", {}, "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="],
|
||||||
|
|
||||||
|
"babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="],
|
||||||
|
|
||||||
"expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@babel/traverse/@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
|
"expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@babel/traverse/@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
|
||||||
|
|
||||||
"expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@babel/traverse/@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="],
|
"expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@babel/traverse/@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="],
|
||||||
|
|
||||||
"expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@babel/traverse/@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
"expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@babel/traverse/@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
|
||||||
|
|
||||||
|
"expo/babel-preset-expo/@react-native/babel-preset/babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
|
||||||
|
|
||||||
"logkitty/yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
"logkitty/yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro/metro-config/cosmiconfig/import-fresh/resolve-from": ["resolve-from@3.0.0", "", {}, "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw=="],
|
||||||
|
|
||||||
|
"metro-transform-worker/metro/metro-config/cosmiconfig/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
|
||||||
|
|
||||||
"qrcode/yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
"qrcode/yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
||||||
|
|
||||||
"expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@babel/traverse/@babel/generator/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
"expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen/@babel/traverse/@babel/generator/@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||||
|
|||||||
@@ -12,10 +12,12 @@ const LeftButtonCustom = ({
|
|||||||
path,
|
path,
|
||||||
icon = "arrow-back",
|
icon = "arrow-back",
|
||||||
iconCustom,
|
iconCustom,
|
||||||
|
onPress,
|
||||||
}: {
|
}: {
|
||||||
path?: Href;
|
path?: Href;
|
||||||
icon?: React.ReactNode | any;
|
icon?: React.ReactNode | any;
|
||||||
iconCustom?: React.ReactNode;
|
iconCustom?: React.ReactNode;
|
||||||
|
onPress?: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -26,7 +28,7 @@ const LeftButtonCustom = ({
|
|||||||
name={icon}
|
name={icon}
|
||||||
size={20}
|
size={20}
|
||||||
color={MainColor.yellow}
|
color={MainColor.yellow}
|
||||||
onPress={() => (path ? router.replace(path) : router.back())}
|
onPress={() => (onPress ? onPress() : path ? router.replace(path) : router.back())}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
29
components/Button/BackButtonFromNotification.tsx
Normal file
29
components/Button/BackButtonFromNotification.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { useRouter } from "expo-router";
|
||||||
|
import { BackButton } from "..";
|
||||||
|
|
||||||
|
export default function BackButtonFromNotification({
|
||||||
|
from,
|
||||||
|
category,
|
||||||
|
}: {
|
||||||
|
from: string;
|
||||||
|
category?: string;
|
||||||
|
}) {
|
||||||
|
const router = useRouter();
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<BackButton
|
||||||
|
onPress={() => {
|
||||||
|
if (from === "notifications") {
|
||||||
|
router.replace(`/notifications?category=${category}`);
|
||||||
|
} else {
|
||||||
|
if (from) {
|
||||||
|
router.replace(`/${from}` as any);
|
||||||
|
} else {
|
||||||
|
router.navigate("/home");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -24,8 +24,6 @@ const DateTimePickerCustom: React.FC<Props> = ({
|
|||||||
disabled = false,
|
disabled = false,
|
||||||
}) => {
|
}) => {
|
||||||
|
|
||||||
console.log("Date Android Comp", value)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{Platform.OS === "ios" ? (
|
{Platform.OS === "ios" ? (
|
||||||
|
|||||||
140
components/Notification/BackgroundNotificationHandler.tsx
Normal file
140
components/Notification/BackgroundNotificationHandler.tsx
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
// src/components/BackgroundNotificationHandler.tsx
|
||||||
|
import { useNotificationStore } from "@/hooks/use-notification-store";
|
||||||
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||||
|
import {
|
||||||
|
FirebaseMessagingTypes,
|
||||||
|
getInitialNotification,
|
||||||
|
getMessaging,
|
||||||
|
onNotificationOpenedApp,
|
||||||
|
} from "@react-native-firebase/messaging";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
|
const HANDLED_NOTIFICATIONS_KEY = "handled_notifications";
|
||||||
|
|
||||||
|
export default function BackgroundNotificationHandler() {
|
||||||
|
const { addNotification, markAsRead } = useNotificationStore();
|
||||||
|
const messaging = getMessaging();
|
||||||
|
const unsubscribeRef = useRef<(() => void) | null>(null); // 🔑 cegah duplikasi
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const init = async () => {
|
||||||
|
// 1. Handle (cold start)
|
||||||
|
const initialNotification = await getInitialNotification(messaging);
|
||||||
|
if (initialNotification) {
|
||||||
|
handleNotification(initialNotification);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Handle background
|
||||||
|
if (unsubscribeRef.current) {
|
||||||
|
unsubscribeRef.current();
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsubscribe = onNotificationOpenedApp(
|
||||||
|
messaging,
|
||||||
|
(remoteMessage) => {
|
||||||
|
handleNotification(remoteMessage);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
unsubscribeRef.current = unsubscribe;
|
||||||
|
};
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
// Cleanup saat komponen unmount
|
||||||
|
return () => {
|
||||||
|
if (unsubscribeRef.current) {
|
||||||
|
unsubscribeRef.current();
|
||||||
|
unsubscribeRef.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [addNotification, messaging]);
|
||||||
|
|
||||||
|
const isNotificationHandled = async (
|
||||||
|
notificationId: string
|
||||||
|
): Promise<boolean> => {
|
||||||
|
const handled = await AsyncStorage.getItem(HANDLED_NOTIFICATIONS_KEY);
|
||||||
|
const ids = handled ? JSON.parse(handled) : [];
|
||||||
|
return ids.includes(notificationId);
|
||||||
|
};
|
||||||
|
|
||||||
|
const markNotificationAsHandled = async (notificationId: string) => {
|
||||||
|
const handled = await AsyncStorage.getItem(HANDLED_NOTIFICATIONS_KEY);
|
||||||
|
const ids = handled ? JSON.parse(handled) : [];
|
||||||
|
if (!ids.includes(notificationId)) {
|
||||||
|
ids.push(notificationId);
|
||||||
|
// Simpan maksimal 50 ID terakhir untuk hindari memori bocor
|
||||||
|
await AsyncStorage.setItem(
|
||||||
|
HANDLED_NOTIFICATIONS_KEY,
|
||||||
|
JSON.stringify(ids.slice(-50))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNotification = async (
|
||||||
|
remoteMessage: FirebaseMessagingTypes.RemoteMessage
|
||||||
|
) => {
|
||||||
|
const { notification, data } = remoteMessage;
|
||||||
|
if (!notification?.title) return;
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"🚀 Notification received:",
|
||||||
|
JSON.stringify(remoteMessage, null, 2)
|
||||||
|
);
|
||||||
|
|
||||||
|
const notificationId = data?.id;
|
||||||
|
if (!notificationId || typeof notificationId !== "string") {
|
||||||
|
console.warn("Notification missing notificationId, skipping navigation");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Cek apakah sudah pernah ditangani
|
||||||
|
if (await isNotificationHandled(notificationId)) {
|
||||||
|
console.log("Notification already handled, skipping:", notificationId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Tandai sebagai ditangani
|
||||||
|
await markNotificationAsHandled(notificationId);
|
||||||
|
|
||||||
|
// ✅ Normalisasi deepLink: pastikan string
|
||||||
|
let deepLink: string | undefined;
|
||||||
|
if (data?.deepLink) {
|
||||||
|
if (typeof data.deepLink === "string") {
|
||||||
|
deepLink = data.deepLink;
|
||||||
|
} else {
|
||||||
|
// Jika object (jarang), coba string-kan
|
||||||
|
deepLink = JSON.stringify(data.deepLink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tambahkan ke UI state (agar muncul di daftar notifikasi & badge)
|
||||||
|
addNotification({
|
||||||
|
title: notification.title,
|
||||||
|
body: notification.body || "",
|
||||||
|
type: "announcement",
|
||||||
|
data: data as Record<string, string>, // aman karena di-normalisasi di useNotificationStore
|
||||||
|
});
|
||||||
|
|
||||||
|
markAsRead(data?.id as any);
|
||||||
|
|
||||||
|
// Navigasi
|
||||||
|
if (
|
||||||
|
data?.deepLink &&
|
||||||
|
typeof data.deepLink === "string" &&
|
||||||
|
data.deepLink.startsWith("/")
|
||||||
|
) {
|
||||||
|
setTimeout(() => {
|
||||||
|
try {
|
||||||
|
router.push(data.deepLink as any);
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Navigation failed:", error);
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
112
components/Notification/NotificationInitializer.tsx
Normal file
112
components/Notification/NotificationInitializer.tsx
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
// src/components/NotificationInitializer.tsx
|
||||||
|
import { useEffect } from "react";
|
||||||
|
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-device-token";
|
||||||
|
import messaging, {
|
||||||
|
isSupported,
|
||||||
|
requestPermission,
|
||||||
|
getToken,
|
||||||
|
AuthorizationStatus,
|
||||||
|
} from "@react-native-firebase/messaging";
|
||||||
|
|
||||||
|
// ✅ Modular imports (sesuai v22+)
|
||||||
|
|
||||||
|
export default function NotificationInitializer() {
|
||||||
|
// Setup handler notifikasi
|
||||||
|
const { user, logout } = 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
const registerDeviceToken = async () => {
|
||||||
|
try {
|
||||||
|
// ✅ Dapatkan instance messaging
|
||||||
|
const messagingInstance = messaging();
|
||||||
|
|
||||||
|
// ✅ Gunakan instance sebagai argumen
|
||||||
|
const supported = await isSupported(messagingInstance);
|
||||||
|
if (!supported) {
|
||||||
|
console.log("‼️ FCM tidak didukung");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const authStatus = await requestPermission(messagingInstance);
|
||||||
|
if (authStatus !== AuthorizationStatus.AUTHORIZED) {
|
||||||
|
console.warn("Izin telah ditolak");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fcmToken = await getToken(messagingInstance);
|
||||||
|
if (!fcmToken) {
|
||||||
|
console.warn("Tidak bisa mendapatkan FCM token");
|
||||||
|
// logout();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("✅ FCM Token:", fcmToken);
|
||||||
|
|
||||||
|
const platform = Platform.OS; // "ios" | "android"
|
||||||
|
const model = Device.modelName || "unknown";
|
||||||
|
const appVersion =
|
||||||
|
(Application.nativeApplicationVersion || "unknown") +
|
||||||
|
"-" +
|
||||||
|
(Application.nativeBuildVersion || "unknown");
|
||||||
|
const deviceId =
|
||||||
|
Device.osInternalBuildId || Device.modelName || "unknown";
|
||||||
|
|
||||||
|
// 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, type: "announcement" });
|
||||||
|
console.log("✅ Notifikasi ditambahkan ke state");
|
||||||
|
};
|
||||||
|
|
||||||
|
useForegroundNotifications(handleForegroundNotification);
|
||||||
|
|
||||||
|
return null; // komponen ini tidak merender apa-apa
|
||||||
|
}
|
||||||
@@ -98,13 +98,14 @@ export const IconView = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const IconDot = ({ size, color }: { size?: number; color?: string }) => {
|
export const IconDot = ({ size, color, onPress }: { size?: number; color?: string , onPress?: () => void}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Ionicons
|
<Ionicons
|
||||||
name="ellipsis-vertical"
|
name="ellipsis-vertical"
|
||||||
size={size || ICON_SIZE_MEDIUM}
|
size={size || ICON_SIZE_MEDIUM}
|
||||||
color={color || MainColor.darkblue}
|
color={color || MainColor.darkblue}
|
||||||
|
onPress={onPress}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,12 +4,21 @@ import { Octicons } from "@expo/vector-icons";
|
|||||||
|
|
||||||
export { IconPlus };
|
export { IconPlus };
|
||||||
|
|
||||||
function IconPlus({ color, size }: { color?: string; size?: number }) {
|
function IconPlus({
|
||||||
|
color,
|
||||||
|
size,
|
||||||
|
onPress,
|
||||||
|
}: {
|
||||||
|
color?: string;
|
||||||
|
size?: number;
|
||||||
|
onPress?: () => void;
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<Octicons
|
<Octicons
|
||||||
name="plus-circle"
|
name="plus-circle"
|
||||||
size={size || ICON_SIZE_MEDIUM}
|
size={size || ICON_SIZE_MEDIUM}
|
||||||
color={color || MainColor.white}
|
color={color || MainColor.white}
|
||||||
|
onPress={onPress}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ import {
|
|||||||
apiConfig,
|
apiConfig,
|
||||||
apiLogin,
|
apiLogin,
|
||||||
apiRegister,
|
apiRegister,
|
||||||
|
apiUpdatedTermCondition,
|
||||||
apiValidationCode,
|
apiValidationCode,
|
||||||
} from "@/service/api-config";
|
} from "@/service/api-config";
|
||||||
|
import { apiDeviceTokenDeleted } from "@/service/api-device-token";
|
||||||
import { IUser } from "@/types/User";
|
import { IUser } from "@/types/User";
|
||||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||||
|
import * as Device from "expo-device";
|
||||||
import { router } from "expo-router";
|
import { router } from "expo-router";
|
||||||
import { createContext, useEffect, useState } from "react";
|
import { createContext, useEffect, useState } from "react";
|
||||||
import Toast from "react-native-toast-message";
|
import Toast from "react-native-toast-message";
|
||||||
@@ -27,6 +30,7 @@ type AuthContextType = {
|
|||||||
termsOfServiceAccepted: boolean;
|
termsOfServiceAccepted: boolean;
|
||||||
}) => Promise<void>;
|
}) => Promise<void>;
|
||||||
userData: (token: string) => Promise<any>;
|
userData: (token: string) => Promise<any>;
|
||||||
|
acceptedTerms: (nomor: string) => Promise<any>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Create Context ---
|
// --- Create Context ---
|
||||||
@@ -72,29 +76,32 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
const loginWithNomor = async (nomor: string) => {
|
const loginWithNomor = async (nomor: string) => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
console.log("[Masuk provider]", nomor);
|
|
||||||
const response = await apiLogin({ nomor: nomor });
|
const response = await apiLogin({ nomor: nomor });
|
||||||
console.log("[RESPONSE AUTH]", JSON.stringify(response));
|
console.log("[RESPONSE AUTH]", JSON.stringify(response, null, 2));
|
||||||
|
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
console.log("[Keluar provider]", nomor);
|
if (response.isAcceptTerms) {
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: "success",
|
type: "success",
|
||||||
text1: "Sukses",
|
text1: "Sukses",
|
||||||
text2: "Kode OTP berhasil dikirim",
|
text2: "Kode OTP berhasil dikirim",
|
||||||
});
|
});
|
||||||
|
|
||||||
await AsyncStorage.setItem("kode_otp", response.kodeId);
|
await AsyncStorage.setItem("kode_otp", response.kodeId);
|
||||||
router.push(`/verification?nomor=${nomor}`);
|
router.push(`/verification?nomor=${nomor}`);
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
router.push(`/eula?nomor=${nomor}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
router.push(`/register?nomor=${nomor}`);
|
router.push(`/eula?nomor=${nomor}`);
|
||||||
Toast.show({
|
|
||||||
type: "info",
|
// Toast.show({
|
||||||
text1: "Info",
|
// type: "info",
|
||||||
text2: "Silahkan mendaftar",
|
// text1: "Info",
|
||||||
});
|
// text2: "Silahkan mendaftar",
|
||||||
|
// });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -104,18 +111,6 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// const loginWithNomor = async (nomor: string) => {
|
|
||||||
// setIsLoading(true);
|
|
||||||
// try {
|
|
||||||
// const response = await apiLogin({ nomor: nomor });
|
|
||||||
// await AsyncStorage.setItem("kode_otp", response.kodeId);
|
|
||||||
// } catch (error: any) {
|
|
||||||
// throw new Error(error.response?.data?.message || "Gagal kirim OTP");
|
|
||||||
// } finally {
|
|
||||||
// setIsLoading(false);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// --- 2. Validasi OTP & cek user ---
|
// --- 2. Validasi OTP & cek user ---
|
||||||
const validateOtp = async (nomor: string) => {
|
const validateOtp = async (nomor: string) => {
|
||||||
try {
|
try {
|
||||||
@@ -139,13 +134,15 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
await AsyncStorage.setItem("userData", JSON.stringify(dataUser));
|
await AsyncStorage.setItem("userData", JSON.stringify(dataUser));
|
||||||
|
|
||||||
if (response.active) {
|
if (response.active) {
|
||||||
if (response.roleId === "1") {
|
// if (response.roleId === "1") {
|
||||||
router.replace("/(application)/(user)/home");
|
// router.replace("/(application)/(user)/home");
|
||||||
return;
|
// return;
|
||||||
} else {
|
// } else {
|
||||||
router.replace("/(application)/admin/dashboard");
|
// router.replace("/(application)/admin/dashboard");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
router.replace("/(application)/(user)/home");
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
router.replace("/(application)/(user)/waiting-room");
|
router.replace("/(application)/(user)/waiting-room");
|
||||||
return;
|
return;
|
||||||
@@ -206,7 +203,6 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
try {
|
try {
|
||||||
const response = await apiRegister({ data: userData });
|
const response = await apiRegister({ data: userData });
|
||||||
console.log("[REGISTER FETCH]", JSON.stringify(response, null, 2));
|
|
||||||
|
|
||||||
if (!response.success) {
|
if (!response.success) {
|
||||||
Toast.show({
|
Toast.show({
|
||||||
@@ -236,42 +232,6 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// const registerUser = async (userData: {
|
|
||||||
// username: string;
|
|
||||||
// nomor: string;
|
|
||||||
// termsOfServiceAccepted: boolean;
|
|
||||||
// }) => {
|
|
||||||
// setIsLoading(true);
|
|
||||||
// try {
|
|
||||||
// const response = await apiRegister({ data: userData });
|
|
||||||
// console.log("response", response);
|
|
||||||
|
|
||||||
// const { token } = response;
|
|
||||||
// if (!response.success) {
|
|
||||||
// Toast.show({
|
|
||||||
// type: "info",
|
|
||||||
// text1: "Info",
|
|
||||||
// text2: response.message,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// setToken(token);
|
|
||||||
// await AsyncStorage.setItem("authToken", token);
|
|
||||||
// Toast.show({
|
|
||||||
// type: "success",
|
|
||||||
// text1: "Sukses",
|
|
||||||
// text2: "Anda berhasil terdaftar",
|
|
||||||
// });
|
|
||||||
// router.replace("/(application)/(user)/waiting-room");
|
|
||||||
// return;
|
|
||||||
// } catch (error: any) {
|
|
||||||
// console.log("Error register", error);
|
|
||||||
// } finally {
|
|
||||||
// setIsLoading(false);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// --- 5. Logout ---
|
// --- 5. Logout ---
|
||||||
|
|
||||||
@@ -280,9 +240,13 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
setToken(null);
|
setToken(null);
|
||||||
setUser(null);
|
setUser(null);
|
||||||
|
|
||||||
|
const deviceId =
|
||||||
|
Device.osInternalBuildId || Device.modelName || "unknown";
|
||||||
|
|
||||||
await AsyncStorage.removeItem("authToken");
|
await AsyncStorage.removeItem("authToken");
|
||||||
await AsyncStorage.removeItem("userData");
|
await AsyncStorage.removeItem("userData");
|
||||||
setIsLoading(false);
|
await apiDeviceTokenDeleted({ userId: user?.id as any, deviceId });
|
||||||
|
|
||||||
Toast.show({
|
Toast.show({
|
||||||
type: "success",
|
type: "success",
|
||||||
@@ -297,6 +261,31 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const acceptedTerms = async (nomor: string) => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
const response = await apiUpdatedTermCondition({ nomor: nomor });
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
router.replace(`/verification?nomor=${nomor}`);
|
||||||
|
} else {
|
||||||
|
if (response.status === 404) {
|
||||||
|
router.replace(`/register?nomor=${nomor}`);
|
||||||
|
} else {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Error",
|
||||||
|
text2: response.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error accept terms", error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AuthContext.Provider
|
<AuthContext.Provider
|
||||||
@@ -312,6 +301,7 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
logout,
|
logout,
|
||||||
registerUser,
|
registerUser,
|
||||||
userData,
|
userData,
|
||||||
|
acceptedTerms,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
2
eas.json
2
eas.json
@@ -11,7 +11,7 @@
|
|||||||
"preview": {
|
"preview": {
|
||||||
"distribution": "internal",
|
"distribution": "internal",
|
||||||
"android": {
|
"android": {
|
||||||
"buildType": "app-bundle"
|
"buildType": "apk"
|
||||||
},
|
},
|
||||||
"ios": {
|
"ios": {
|
||||||
"simulator": false
|
"simulator": false
|
||||||
|
|||||||
@@ -13,3 +13,13 @@ Exp: open ios/HIPMIBADUNG.xcworkspace
|
|||||||
perubahan versi : npm version patch
|
perubahan versi : npm version patch
|
||||||
ios: bunx expo prebuild --platform ios
|
ios: bunx expo prebuild --platform ios
|
||||||
android: bunx expo prebuild --platform android
|
android: bunx expo prebuild --platform android
|
||||||
|
|
||||||
|
### Android
|
||||||
|
adb devices : cek device yang terhubung
|
||||||
|
Note: izinkan perangkat dulu agar statusnya tidak unauthorized
|
||||||
|
|
||||||
|
adb install android/app/build/outputs/apk/debug/app-debug.apk : install apk ke device
|
||||||
|
Note:
|
||||||
|
Gunakan flag -s (serial) di perintah adb untuk menentukan target
|
||||||
|
adb -s <0G52319V261040B2 ini adalah id nya> install android/app/build/outputs/apk/debug/app-debug.apk
|
||||||
|
|
||||||
|
|||||||
37
hooks/use-foreground-notifications.ts
Normal file
37
hooks/use-foreground-notifications.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
import {
|
||||||
|
getMessaging,
|
||||||
|
onMessage,
|
||||||
|
FirebaseMessagingTypes,
|
||||||
|
} from "@react-native-firebase/messaging";
|
||||||
|
import { useAuth } from "./use-auth";
|
||||||
|
|
||||||
|
// Gunakan tipe resmi dari library
|
||||||
|
type RemoteMessage = FirebaseMessagingTypes.RemoteMessage;
|
||||||
|
|
||||||
|
export function useForegroundNotifications(
|
||||||
|
onMessageReceived: (message: RemoteMessage) => void
|
||||||
|
) {
|
||||||
|
const { user } = useAuth();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const messaging = getMessaging();
|
||||||
|
|
||||||
|
const unsubscribe = onMessage(messaging, (remoteMessage) => {
|
||||||
|
const data = remoteMessage.data;
|
||||||
|
// console.log("DATA NOTIFIKASI DARI SERVER", data)
|
||||||
|
if (data?.recipientId && data?.recipientId !== user?.id) {
|
||||||
|
console.log("📵 Notification untuk user lain", data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"🔔 Notifikasi diterima saat app aktif:",
|
||||||
|
JSON.stringify(data, null, 2)
|
||||||
|
);
|
||||||
|
onMessageReceived(remoteMessage);
|
||||||
|
});
|
||||||
|
|
||||||
|
return unsubscribe;
|
||||||
|
}, [user?.id, onMessageReceived]);
|
||||||
|
}
|
||||||
168
hooks/use-notification-store.tsx
Normal file
168
hooks/use-notification-store.tsx
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
// hooks/useNotificationStore.ts
|
||||||
|
import {
|
||||||
|
apiNotificationMarkAsRead,
|
||||||
|
apiNotificationUnreadCount,
|
||||||
|
} from "@/service/api-notifications";
|
||||||
|
import {
|
||||||
|
createContext,
|
||||||
|
ReactNode,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
import { useAuth } from "./use-auth";
|
||||||
|
|
||||||
|
type AppNotification = {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
body: string;
|
||||||
|
data?: Record<string, string>;
|
||||||
|
isRead: boolean;
|
||||||
|
timestamp: number;
|
||||||
|
type: "announcement" | "trigger";
|
||||||
|
// untuk id dari setiap kategori app
|
||||||
|
appId?: string;
|
||||||
|
kategoriApp?:
|
||||||
|
| "JOB"
|
||||||
|
| "VOTING"
|
||||||
|
| "EVENT"
|
||||||
|
| "DONASI"
|
||||||
|
| "INVESTASI"
|
||||||
|
| "COLLABORATION"
|
||||||
|
| "FORUM"
|
||||||
|
| "ACCESS"; // Untuk trigger akses user;
|
||||||
|
};
|
||||||
|
|
||||||
|
type NotificationContextType = {
|
||||||
|
notifications: AppNotification[];
|
||||||
|
unreadCount: number;
|
||||||
|
addNotification: (
|
||||||
|
notif: Omit<AppNotification, "id" | "isRead" | "timestamp">
|
||||||
|
) => void;
|
||||||
|
markAsRead: (id: string) => void;
|
||||||
|
markAsReadAll: (id: string) => void;
|
||||||
|
syncUnreadCount: () => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const NotificationContext = createContext<NotificationContextType>({
|
||||||
|
notifications: [],
|
||||||
|
unreadCount: 0,
|
||||||
|
addNotification: () => {},
|
||||||
|
markAsRead: () => {},
|
||||||
|
markAsReadAll: () => {},
|
||||||
|
syncUnreadCount: async () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const NotificationProvider = ({ children }: { children: ReactNode }) => {
|
||||||
|
const { user } = useAuth();
|
||||||
|
const [notifications, setNotifications] = useState<AppNotification[]>([]);
|
||||||
|
const [unreadCount, setUnreadCount] = useState(0);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"🚀 Notifications Masuk:",
|
||||||
|
JSON.stringify(notifications, null, 2)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Sync unread count dari backend saat provider di-mount
|
||||||
|
useEffect(() => {
|
||||||
|
fetchUnreadCount();
|
||||||
|
}, [user?.id]);
|
||||||
|
|
||||||
|
const fetchUnreadCount = async () => {
|
||||||
|
try {
|
||||||
|
const count = await apiNotificationUnreadCount({
|
||||||
|
id: user?.id as any,
|
||||||
|
role: user?.masterUserRoleId as any,
|
||||||
|
}); // ← harus return number
|
||||||
|
const result = count.data;
|
||||||
|
console.log("📖 Unread count:", result);
|
||||||
|
setUnreadCount(result);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Gagal fetch unread count:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addNotification = (
|
||||||
|
notif: Omit<AppNotification, "id" | "isRead" | "timestamp">
|
||||||
|
) => {
|
||||||
|
setNotifications((prev) => [
|
||||||
|
{
|
||||||
|
...notif,
|
||||||
|
id: Date.now().toString(),
|
||||||
|
isRead: false,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
},
|
||||||
|
...prev,
|
||||||
|
]);
|
||||||
|
|
||||||
|
setUnreadCount((prev) => prev + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const markAsRead = async (id: string) => {
|
||||||
|
try {
|
||||||
|
const response = await apiNotificationMarkAsRead({ id, category: "one" });
|
||||||
|
console.log("🚀 Response Mark As Read:", response);
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
const cloneNotifications = [...notifications];
|
||||||
|
const index = cloneNotifications.findIndex((n) => n?.data?.id === id);
|
||||||
|
if (index !== -1) {
|
||||||
|
cloneNotifications[index].isRead = true;
|
||||||
|
setNotifications(cloneNotifications);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Gagal mark as read:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const markAsReadAll = async (id: string) => {
|
||||||
|
try {
|
||||||
|
const response = await apiNotificationMarkAsRead({ id, category: "all" });
|
||||||
|
console.log("🚀 Response Mark As Read All:", response);
|
||||||
|
|
||||||
|
if (response.success) {
|
||||||
|
const cloneNotifications = [...notifications];
|
||||||
|
const index = cloneNotifications.findIndex((n) => n?.data?.id === id);
|
||||||
|
if (index !== -1) {
|
||||||
|
cloneNotifications[index].isRead = true;
|
||||||
|
setNotifications(cloneNotifications);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Gagal mark as read:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const syncUnreadCount = async () => {
|
||||||
|
try {
|
||||||
|
const count = await apiNotificationUnreadCount({
|
||||||
|
id: user?.id as any,
|
||||||
|
role: user?.masterUserRoleId as any,
|
||||||
|
}); // ← harus return number
|
||||||
|
const result = count.data;
|
||||||
|
console.log("📖 Unread count sync:", result);
|
||||||
|
setUnreadCount(result);
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("⚠️ Gagal sync unread count:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NotificationContext.Provider
|
||||||
|
value={{
|
||||||
|
notifications,
|
||||||
|
addNotification,
|
||||||
|
unreadCount,
|
||||||
|
markAsRead,
|
||||||
|
markAsReadAll,
|
||||||
|
syncUnreadCount,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</NotificationContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useNotificationStore = () => useContext(NotificationContext);
|
||||||
113
hooks/use-notification-store.tsx.back
Normal file
113
hooks/use-notification-store.tsx.back
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
// hooks/useNotificationStore.ts
|
||||||
|
import { apiGetNotificationsById } from "@/service/api-notifications";
|
||||||
|
import { createContext, ReactNode, useContext, useState, useEffect } from "react";
|
||||||
|
import { useAuth } from "./use-auth";
|
||||||
|
|
||||||
|
type AppNotification = {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
body: string;
|
||||||
|
data?: Record<string, string>;
|
||||||
|
isRead: boolean;
|
||||||
|
timestamp: number;
|
||||||
|
type: "notification" | "trigger";
|
||||||
|
appId?: string;
|
||||||
|
kategoriApp?:
|
||||||
|
| "JOB"
|
||||||
|
| "VOTING"
|
||||||
|
| "EVENT"
|
||||||
|
| "DONASI"
|
||||||
|
| "INVESTASI"
|
||||||
|
| "COLLABORATION"
|
||||||
|
| "FORUM"
|
||||||
|
| "ACCESS";
|
||||||
|
};
|
||||||
|
|
||||||
|
type NotificationContextType = {
|
||||||
|
notifications: AppNotification[];
|
||||||
|
unreadCount: number;
|
||||||
|
addNotification: (
|
||||||
|
notif: Omit<AppNotification, "id" | "isRead" | "timestamp">
|
||||||
|
) => void;
|
||||||
|
markAsRead: (id: string) => void;
|
||||||
|
syncUnreadCount: () => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const NotificationContext = createContext<NotificationContextType>({
|
||||||
|
notifications: [],
|
||||||
|
unreadCount: 0,
|
||||||
|
addNotification: () => {},
|
||||||
|
markAsRead: () => {},
|
||||||
|
syncUnreadCount: async () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const NotificationProvider = ({ children }: { children: ReactNode }) => {
|
||||||
|
const {user} = useAuth()
|
||||||
|
const [notifications, setNotifications] = useState<AppNotification[]>([]);
|
||||||
|
const [unreadCount, setUnreadCount] = useState(0);
|
||||||
|
|
||||||
|
// 🔔 Sync unread count dari backend saat provider di-mount
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchUnreadCount = async () => {
|
||||||
|
try {
|
||||||
|
const count = await apiGetNotificationsById({
|
||||||
|
id: user?.id as any,
|
||||||
|
category: "count-as-unread"
|
||||||
|
}); // ← harus return number
|
||||||
|
const result = count.data
|
||||||
|
setUnreadCount(result);
|
||||||
|
} catch (error) {
|
||||||
|
console.erro("⚠️ Gagal fetch unread count:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchUnreadCount();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const addNotification = (
|
||||||
|
notif: Omit<AppNotification, "id" | "isRead" | "timestamp">
|
||||||
|
) => {
|
||||||
|
setNotifications((prev) => [
|
||||||
|
{
|
||||||
|
...notif,
|
||||||
|
id: Date.now().toString(),
|
||||||
|
isRead: false,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
},
|
||||||
|
...prev,
|
||||||
|
]);
|
||||||
|
// Tambahkan ke unread count (untuk notifikasi foreground)
|
||||||
|
setUnreadCount((prev) => prev + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
const markAsRead = (id: string) => {
|
||||||
|
setNotifications((prev) =>
|
||||||
|
prev.map((n) => (n.id === id ? { ...n, isRead: true } : n))
|
||||||
|
);
|
||||||
|
// Kurangi unread count
|
||||||
|
setUnreadCount((prev) => Math.max(0, prev - 1));
|
||||||
|
};
|
||||||
|
|
||||||
|
const syncUnreadCount = async () => {
|
||||||
|
try {
|
||||||
|
const count = await apiGetNotificationsById({
|
||||||
|
id: user?.id as any,
|
||||||
|
category: "count-as-unread"
|
||||||
|
}); // ← harus return number
|
||||||
|
const result = count.data
|
||||||
|
setUnreadCount(result);
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("⚠️ Gagal sync unread count:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NotificationContext.Provider
|
||||||
|
value={{ notifications, unreadCount, addNotification, markAsRead, syncUnreadCount }}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</NotificationContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useNotificationStore = () => useContext(NotificationContext);
|
||||||
File diff suppressed because one or more lines are too long
@@ -39,7 +39,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>15</string>
|
<string>19</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>
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ 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'
|
pod 'Firebase/Messaging'
|
||||||
|
|
||||||
# @generated begin post_installer - expo prebuild (DO NOT MODIFY) sync-4092f82b887b5b9edb84642c2a56984d69b9a403
|
# @generated begin post_installer - expo prebuild (DO NOT MODIFY) sync-4092f82b887b5b9edb84642c2a56984d69b9a403
|
||||||
|
|||||||
116
ios/Podfile.lock
116
ios/Podfile.lock
@@ -279,31 +279,83 @@ PODS:
|
|||||||
- EXUpdatesInterface (2.0.0):
|
- EXUpdatesInterface (2.0.0):
|
||||||
- ExpoModulesCore
|
- ExpoModulesCore
|
||||||
- FBLazyVector (0.81.4)
|
- FBLazyVector (0.81.4)
|
||||||
- Firebase/CoreOnly (12.7.0):
|
- Firebase (12.6.0):
|
||||||
- FirebaseCore (~> 12.7.0)
|
- Firebase/Core (= 12.6.0)
|
||||||
- Firebase/Messaging (12.7.0):
|
- Firebase/Core (12.6.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseMessaging (~> 12.7.0)
|
- FirebaseAnalytics (~> 12.6.0)
|
||||||
- FirebaseCore (12.7.0):
|
- Firebase/CoreOnly (12.6.0):
|
||||||
- FirebaseCoreInternal (~> 12.7.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/Environment (~> 8.1)
|
||||||
- GoogleUtilities/Logger (~> 8.1)
|
- GoogleUtilities/Logger (~> 8.1)
|
||||||
- FirebaseCoreInternal (12.7.0):
|
- FirebaseCoreExtension (12.6.0):
|
||||||
|
- FirebaseCore (~> 12.6.0)
|
||||||
|
- FirebaseCoreInternal (12.6.0):
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- FirebaseInstallations (12.7.0):
|
- FirebaseInstallations (12.6.0):
|
||||||
- FirebaseCore (~> 12.7.0)
|
- FirebaseCore (~> 12.6.0)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
- PromisesObjC (~> 2.4)
|
- PromisesObjC (~> 2.4)
|
||||||
- FirebaseMessaging (12.7.0):
|
- FirebaseMessaging (12.6.0):
|
||||||
- FirebaseCore (~> 12.7.0)
|
- FirebaseCore (~> 12.6.0)
|
||||||
- FirebaseInstallations (~> 12.7.0)
|
- FirebaseInstallations (~> 12.6.0)
|
||||||
- GoogleDataTransport (~> 10.1)
|
- GoogleDataTransport (~> 10.1)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/Reachability (~> 8.1)
|
- GoogleUtilities/Reachability (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
- nanopb (~> 3.30910.0)
|
- 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):
|
- GoogleDataTransport (10.1.0):
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- PromisesObjC (~> 2.4)
|
- PromisesObjC (~> 2.4)
|
||||||
@@ -317,6 +369,9 @@ PODS:
|
|||||||
- GoogleUtilities/Logger (8.1.0):
|
- GoogleUtilities/Logger (8.1.0):
|
||||||
- GoogleUtilities/Environment
|
- GoogleUtilities/Environment
|
||||||
- GoogleUtilities/Privacy
|
- GoogleUtilities/Privacy
|
||||||
|
- GoogleUtilities/MethodSwizzler (8.1.0):
|
||||||
|
- GoogleUtilities/Logger
|
||||||
|
- GoogleUtilities/Privacy
|
||||||
- GoogleUtilities/Network (8.1.0):
|
- GoogleUtilities/Network (8.1.0):
|
||||||
- GoogleUtilities/Logger
|
- GoogleUtilities/Logger
|
||||||
- "GoogleUtilities/NSData+zlib"
|
- "GoogleUtilities/NSData+zlib"
|
||||||
@@ -2198,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
|
||||||
@@ -2559,6 +2622,7 @@ 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
|
- 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`)
|
||||||
@@ -2633,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`)
|
||||||
@@ -2645,10 +2711,14 @@ DEPENDENCIES:
|
|||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
- Firebase
|
- Firebase
|
||||||
|
- FirebaseAnalytics
|
||||||
- FirebaseCore
|
- FirebaseCore
|
||||||
|
- FirebaseCoreExtension
|
||||||
- FirebaseCoreInternal
|
- FirebaseCoreInternal
|
||||||
- FirebaseInstallations
|
- FirebaseInstallations
|
||||||
- FirebaseMessaging
|
- FirebaseMessaging
|
||||||
|
- GoogleAdsOnDeviceConversion
|
||||||
|
- GoogleAppMeasurement
|
||||||
- GoogleDataTransport
|
- GoogleDataTransport
|
||||||
- GoogleUtilities
|
- GoogleUtilities
|
||||||
- libavif
|
- libavif
|
||||||
@@ -2878,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:
|
||||||
@@ -2929,11 +3003,15 @@ SPEC CHECKSUMS:
|
|||||||
ExpoWebBrowser: b973e1351fdcf5fec0c400997b1851f5a8219ec3
|
ExpoWebBrowser: b973e1351fdcf5fec0c400997b1851f5a8219ec3
|
||||||
EXUpdatesInterface: 5adf50cb41e079c861da6d9b4b954c3db9a50734
|
EXUpdatesInterface: 5adf50cb41e079c861da6d9b4b954c3db9a50734
|
||||||
FBLazyVector: 9e0cd874afd81d9a4d36679daca991b58b260d42
|
FBLazyVector: 9e0cd874afd81d9a4d36679daca991b58b260d42
|
||||||
Firebase: 2d19a10c9a2e48ac532a4303115d3fc9b2798396
|
Firebase: a451a7b61536298fd5cbfe3a746fd40443a50679
|
||||||
FirebaseCore: c7b57863ce0859281a66d16ca36d665c45d332b5
|
FirebaseAnalytics: d0a97a0db6425e5a5d966340b87f92ca7b13a557
|
||||||
FirebaseCoreInternal: 571a2dd8c975410966199623351db3a3265c874d
|
FirebaseCore: 0e38ad5d62d980a47a64b8e9301ffa311457be04
|
||||||
FirebaseInstallations: 6d05424a046b68ca146b4de4376f05b4e9262fc3
|
FirebaseCoreExtension: 032fd6f8509e591fda8cb76f6651f20d926b121f
|
||||||
FirebaseMessaging: b5f7bdc62b91b6102015991fb7bc6fa75f643908
|
FirebaseCoreInternal: 69bf1306a05b8ac43004f6cc1f804bb7b05b229e
|
||||||
|
FirebaseInstallations: 631b38da2e11a83daa4bfb482f79d286a5dfa7ad
|
||||||
|
FirebaseMessaging: a61bc42dcab3f7a346d94bbb54dab2c9435b18b2
|
||||||
|
GoogleAdsOnDeviceConversion: d68c69dd9581a0f5da02617b6f377e5be483970f
|
||||||
|
GoogleAppMeasurement: 3bf40aff49a601af5da1c3345702fcb4991d35ee
|
||||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||||
hermes-engine: 35c763d57c9832d0eef764316ca1c4d043581394
|
hermes-engine: 35c763d57c9832d0eef764316ca1c4d043581394
|
||||||
@@ -3016,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
|
||||||
@@ -3031,6 +3111,6 @@ SPEC CHECKSUMS:
|
|||||||
Yoga: 051f086b5ccf465ff2ed38a2cf5a558ae01aaaa1
|
Yoga: 051f086b5ccf465ff2ed38a2cf5a558ae01aaaa1
|
||||||
ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5
|
ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5
|
||||||
|
|
||||||
PODFILE CHECKSUM: 61c4a9d35618e5f2a420f47e5a24c89e86706f00
|
PODFILE CHECKSUM: 9c1ecbc7e57ca21dc7c93635b18e66f8f6d7bdd9
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
9
lib/routeApp.ts
Normal file
9
lib/routeApp.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export { routeAdmin, routeUser };
|
||||||
|
|
||||||
|
const routeAdmin = {
|
||||||
|
userAccess: ({ id }: { id: string }) => `/admin/user-access/${id}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const routeUser = {
|
||||||
|
home: `/(user)/home`,
|
||||||
|
};
|
||||||
@@ -75,6 +75,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
"@react-native-community/cli": "^20.0.2",
|
"@react-native-community/cli": "^20.0.2",
|
||||||
|
"@react-native/metro-config": "^0.83.1",
|
||||||
"@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",
|
||||||
|
|||||||
41
screens/Admin/AdminNotificationBell.tsx
Normal file
41
screens/Admin/AdminNotificationBell.tsx
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
// components/HeaderBell.tsx
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
|
||||||
|
import { useNotificationStore } from "@/hooks/use-notification-store";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { Text, View } from "react-native";
|
||||||
|
|
||||||
|
export default function AdminNotificationBell() {
|
||||||
|
const { unreadCount } = useNotificationStore();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{ position: "relative" }}>
|
||||||
|
<Ionicons
|
||||||
|
name="notifications"
|
||||||
|
size={ICON_SIZE_SMALL}
|
||||||
|
color={MainColor.white}
|
||||||
|
/>
|
||||||
|
{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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { apiAdminEventUpdateStatus } from "@/service/api-admin/api-admin-event";
|
import { apiAdminEventUpdateStatus } from "@/service/api-admin/api-admin-event";
|
||||||
|
import { typeRejectedData } from "@/types/type-collect-other";
|
||||||
|
|
||||||
export const funUpdateStatusEvent = async ({
|
export const funUpdateStatusEvent = async ({
|
||||||
id,
|
id,
|
||||||
@@ -7,15 +8,17 @@ export const funUpdateStatusEvent = async ({
|
|||||||
}: {
|
}: {
|
||||||
id: string;
|
id: string;
|
||||||
changeStatus: "publish" | "review" | "reject";
|
changeStatus: "publish" | "review" | "reject";
|
||||||
data?: string;
|
data?: typeRejectedData;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
try {
|
||||||
|
console.log("[DATA]", data);
|
||||||
const response = await apiAdminEventUpdateStatus({
|
const response = await apiAdminEventUpdateStatus({
|
||||||
id: id,
|
id: id,
|
||||||
changeStatus: changeStatus as any,
|
changeStatus: changeStatus as any,
|
||||||
data: data,
|
data: data as any,
|
||||||
});
|
});
|
||||||
return response;
|
return response;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -7,13 +7,17 @@ const funUpdateStatusJob = async ({
|
|||||||
}: {
|
}: {
|
||||||
id: string;
|
id: string;
|
||||||
changeStatus: "publish" | "review" | "reject";
|
changeStatus: "publish" | "review" | "reject";
|
||||||
data?: string;
|
data: {
|
||||||
|
catatan?: string;
|
||||||
|
senderId: string;
|
||||||
|
};
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
try {
|
||||||
|
const fixData = data;
|
||||||
const response = await apiAdminJobUpdate({
|
const response = await apiAdminJobUpdate({
|
||||||
id: id,
|
id: id,
|
||||||
status: changeStatus as any,
|
status: changeStatus as any,
|
||||||
data: data,
|
data: fixData as any,
|
||||||
});
|
});
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { apiAdminVotingUpdateStatus } from "@/service/api-admin/api-admin-voting";
|
import { apiAdminVotingUpdateStatus } from "@/service/api-admin/api-admin-voting";
|
||||||
|
import { typeRejectedData } from "@/types/type-collect-other";
|
||||||
|
|
||||||
const funUpdateStatusVoting = async ({
|
const funUpdateStatusVoting = async ({
|
||||||
id,
|
id,
|
||||||
@@ -7,7 +8,7 @@ const funUpdateStatusVoting = async ({
|
|||||||
}: {
|
}: {
|
||||||
id: string;
|
id: string;
|
||||||
changeStatus: "publish" | "review" | "reject";
|
changeStatus: "publish" | "review" | "reject";
|
||||||
data?: string;
|
data?: typeRejectedData;
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
try {
|
||||||
const response = await apiAdminVotingUpdateStatus({
|
const response = await apiAdminVotingUpdateStatus({
|
||||||
|
|||||||
278
screens/Authentication/EULAView.tsx
Normal file
278
screens/Authentication/EULAView.tsx
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
// app/syarat-dan-ketentuan.tsx
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
ScrollView,
|
||||||
|
TouchableOpacity,
|
||||||
|
StyleSheet,
|
||||||
|
} from "react-native";
|
||||||
|
import { useState, useRef } from "react";
|
||||||
|
import { useLocalSearchParams, useRouter } from "expo-router";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
|
||||||
|
// Ganti dengan API call ke backend Anda
|
||||||
|
// const acceptEula = async (): Promise<boolean> => {
|
||||||
|
// try {
|
||||||
|
// const response = await fetch("/api/user/update-eula", {
|
||||||
|
// method: "PATCH",
|
||||||
|
// headers: { "Content-Type": "application/json" },
|
||||||
|
// credentials: "include",
|
||||||
|
// body: JSON.stringify({
|
||||||
|
// eulaAcceptedAt: new Date().toISOString(),
|
||||||
|
// eulaVersion: "2026-01-v1", // sesuaikan versi Anda
|
||||||
|
// }),
|
||||||
|
// });
|
||||||
|
// return response.ok;
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("Gagal menyimpan persetujuan EULA:", error);
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
export default function EULAView() {
|
||||||
|
const { acceptedTerms } = useAuth();
|
||||||
|
const { nomor } = useLocalSearchParams();
|
||||||
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
|
const [isAtBottom, setIsAtBottom] = useState(false);
|
||||||
|
const scrollViewRef = useRef<ScrollView>(null);
|
||||||
|
|
||||||
|
const handleScroll = (event: any) => {
|
||||||
|
const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent;
|
||||||
|
const paddingToBottom = 20;
|
||||||
|
const isCloseToBottom =
|
||||||
|
layoutMeasurement.height + contentOffset.y >=
|
||||||
|
contentSize.height - paddingToBottom;
|
||||||
|
setIsAtBottom(isCloseToBottom);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAccept = async () => {
|
||||||
|
try {
|
||||||
|
if (!isAtBottom) return;
|
||||||
|
|
||||||
|
setIsLoading(true);
|
||||||
|
await acceptedTerms(nomor as string);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error accept terms", error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SafeAreaView edges={["bottom"]} style={styles.container}>
|
||||||
|
<Text style={styles.title}>
|
||||||
|
Syarat & Ketentuan Penggunaan HIPMI Badung Connect
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
ref={scrollViewRef}
|
||||||
|
onScroll={handleScroll}
|
||||||
|
scrollEventThrottle={16}
|
||||||
|
style={styles.scrollView}
|
||||||
|
contentContainerStyle={styles.scrollContent}
|
||||||
|
>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
Dengan menggunakan aplikasi{" "}
|
||||||
|
<Text style={styles.bold}>HIPMI Badung Connect</Text> (“Aplikasi”),
|
||||||
|
Anda setuju untuk mematuhi dan terikat oleh syarat dan ketentuan
|
||||||
|
berikut. Jika Anda tidak setuju dengan ketentuan ini, harap jangan
|
||||||
|
gunakan Aplikasi.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={styles.heading}>1. Definisi</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
<Text style={styles.bold}>HIPMI Badung Connect</Text> adalah platform
|
||||||
|
digital resmi untuk anggota Himpunan Pengusaha Muda Indonesia (HIPMI)
|
||||||
|
Kabupaten Badung, yang bertujuan memfasilitasi jaringan, kolaborasi,
|
||||||
|
dan pertumbuhan bisnis para pengusaha muda.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={styles.heading}>2. Larangan Konten Tidak Pantas</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
Anda <Text style={styles.bold}>dilarang keras</Text> memposting,
|
||||||
|
mengirim, membagikan, atau mengunggah konten apa pun yang mengandung:
|
||||||
|
</Text>
|
||||||
|
<View style={styles.list}>
|
||||||
|
<Text style={styles.listItem}>
|
||||||
|
• Ujaran kebencian, diskriminasi, atau konten SARA (Suku, Agama,
|
||||||
|
Ras, Antar-golongan)
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.listItem}>
|
||||||
|
• Pornografi, konten seksual eksplisit, atau gambar tidak senonoh
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.listItem}>
|
||||||
|
• Ancaman, pelecehan, bullying, atau perilaku melecehkan
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.listItem}>
|
||||||
|
• Informasi palsu, hoaks, spam, atau konten menyesatkan
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.listItem}>
|
||||||
|
• Konten ilegal, melanggar hukum, atau melanggar hak kekayaan
|
||||||
|
intelektual pihak lain
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.listItem}>
|
||||||
|
• Promosi narkoba, perjudian, atau aktivitas ilegal lainnya
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text style={styles.heading}>3. Tanggung Jawab Pengguna</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
Anda bertanggung jawab penuh atas setiap konten yang Anda unggah atau
|
||||||
|
bagikan melalui fitur-fitur berikut:
|
||||||
|
</Text>
|
||||||
|
<View style={styles.list}>
|
||||||
|
<Text style={styles.listItem}>• Profil (bio, foto, portofolio)</Text>
|
||||||
|
<Text style={styles.listItem}>• Forum diskusi</Text>
|
||||||
|
<Text style={styles.listItem}>• Chat pribadi atau grup</Text>
|
||||||
|
<Text style={styles.listItem}>
|
||||||
|
• Lowongan kerja, investasi, dan donasi
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
Konten yang melanggar ketentuan ini dapat dihapus kapan saja tanpa
|
||||||
|
pemberitahuan.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={styles.heading}>4. Tindakan terhadap Pelanggaran</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
Jika kami menerima laporan atau menemukan konten yang melanggar
|
||||||
|
ketentuan ini, kami akan:
|
||||||
|
</Text>
|
||||||
|
<View style={styles.list}>
|
||||||
|
<Text style={styles.listItem}>
|
||||||
|
• Segera menghapus konten tersebut
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.listItem}>
|
||||||
|
• Memberikan peringatan atau memblokir akun pengguna
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.listItem}>
|
||||||
|
• Dalam kasus berat, melaporkan ke pihak berwajib sesuai hukum yang
|
||||||
|
berlaku
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
Tim kami berkomitmen untuk menanggapi laporan konten tidak pantas{" "}
|
||||||
|
<Text style={styles.bold}>dalam waktu 24 jam</Text>.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={styles.heading}>5. Mekanisme Pelaporan</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
Anda dapat melaporkan konten atau pengguna yang mencurigakan melalui:
|
||||||
|
</Text>
|
||||||
|
<View style={styles.list}>
|
||||||
|
<Text style={styles.listItem}>
|
||||||
|
• Tombol <Text style={styles.bold}>“Laporkan”</Text> di setiap
|
||||||
|
posting forum atau pesan chat
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.listItem}>
|
||||||
|
• Tombol <Text style={styles.bold}>“Blokir Pengguna”</Text> di
|
||||||
|
profil pengguna
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
Setiap laporan akan ditangani secara rahasia dan segera.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={styles.heading}>6. Perubahan Ketentuan</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
Kami berhak memperbarui Syarat & Ketentuan ini sewaktu-waktu. Versi
|
||||||
|
terbaru akan dipublikasikan di halaman ini dengan tanggal revisi yang
|
||||||
|
diperbarui.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={styles.heading}>7. Kontak</Text>
|
||||||
|
<Text style={styles.paragraph}>
|
||||||
|
Jika Anda memiliki pertanyaan tentang ketentuan ini, silakan hubungi
|
||||||
|
kami di:{"\n"}
|
||||||
|
<Text style={[styles.bold, { color: "#1E90FF" }]}>
|
||||||
|
bip.baliinteraktifperkasa@gmail.com
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text style={styles.footer}>
|
||||||
|
© 2026 Bali Interaktif Perkasa. All rights reserved.
|
||||||
|
</Text>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={handleAccept}
|
||||||
|
disabled={!isAtBottom || isLoading}
|
||||||
|
style={[styles.button, { opacity: !isAtBottom || isLoading ? 0.6 : 1 }]}
|
||||||
|
>
|
||||||
|
<Text style={styles.buttonText}>
|
||||||
|
{isLoading ? "Menyimpan..." : "Saya Setuju"}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: MainColor.darkblue,
|
||||||
|
padding: 16,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "bold",
|
||||||
|
textAlign: "center",
|
||||||
|
marginBottom: 16,
|
||||||
|
color: MainColor.white,
|
||||||
|
},
|
||||||
|
scrollView: {
|
||||||
|
flex: 1,
|
||||||
|
marginBottom: 20,
|
||||||
|
},
|
||||||
|
scrollContent: {
|
||||||
|
paddingBottom: 30,
|
||||||
|
},
|
||||||
|
heading: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "600",
|
||||||
|
marginTop: 16,
|
||||||
|
marginBottom: 8,
|
||||||
|
color: MainColor.white,
|
||||||
|
},
|
||||||
|
paragraph: {
|
||||||
|
fontSize: 14,
|
||||||
|
lineHeight: 22,
|
||||||
|
color: MainColor.white,
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
bold: {
|
||||||
|
fontWeight: "600",
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
marginLeft: 8,
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
listItem: {
|
||||||
|
fontSize: 14,
|
||||||
|
lineHeight: 22,
|
||||||
|
color: MainColor.white,
|
||||||
|
marginBottom: 6,
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
fontSize: 12,
|
||||||
|
color: MainColor.white,
|
||||||
|
textAlign: "center",
|
||||||
|
marginTop: 20,
|
||||||
|
paddingTop: 10,
|
||||||
|
borderTopWidth: 2,
|
||||||
|
borderTopColor: AccentColor.blue,
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
backgroundColor: MainColor.yellow,
|
||||||
|
paddingVertical: 14,
|
||||||
|
borderRadius: 8,
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
color: "#fff",
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "600",
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import { CheckboxCustom } from "@/components";
|
|
||||||
import Spacing from "@/components/_ShareComponent/Spacing";
|
import Spacing from "@/components/_ShareComponent/Spacing";
|
||||||
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
|
||||||
import ButtonCustom from "@/components/Button/ButtonCustom";
|
import ButtonCustom from "@/components/Button/ButtonCustom";
|
||||||
@@ -7,7 +6,6 @@ import { MainColor } from "@/constants/color-palet";
|
|||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import { BASE_URL } from "@/service/api-config";
|
import { BASE_URL } from "@/service/api-config";
|
||||||
import { GStyles } from "@/styles/global-styles";
|
import { GStyles } from "@/styles/global-styles";
|
||||||
import { openBrowser } from "@/utils/openBrower";
|
|
||||||
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
import { MaterialCommunityIcons } from "@expo/vector-icons";
|
||||||
import { useLocalSearchParams } from "expo-router";
|
import { useLocalSearchParams } from "expo-router";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
@@ -17,7 +15,7 @@ import Toast from "react-native-toast-message";
|
|||||||
export default function RegisterView() {
|
export default function RegisterView() {
|
||||||
const { nomor } = useLocalSearchParams();
|
const { nomor } = useLocalSearchParams();
|
||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
const [term, setTerm] = useState(false);
|
// const [term, setTerm] = useState(false);
|
||||||
const url = BASE_URL;
|
const url = BASE_URL;
|
||||||
const { registerUser, isLoading } = useAuth();
|
const { registerUser, isLoading } = useAuth();
|
||||||
|
|
||||||
@@ -65,7 +63,7 @@ export default function RegisterView() {
|
|||||||
await registerUser({
|
await registerUser({
|
||||||
nomor: nomor as string,
|
nomor: nomor as string,
|
||||||
username: usernameLower,
|
username: usernameLower,
|
||||||
termsOfServiceAccepted: term,
|
termsOfServiceAccepted: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,12 +104,12 @@ export default function RegisterView() {
|
|||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
marginTop: 16,
|
marginTop: 16,
|
||||||
marginBottom: 16,
|
// marginBottom: 16,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CheckboxCustom value={term} onChange={() => setTerm(!term)} />
|
{/* <CheckboxCustom value={term} onChange={() => setTerm(!term)} /> */}
|
||||||
|
|
||||||
<Text style={GStyles.textLabel}>
|
{/* <Text style={GStyles.textLabel}>
|
||||||
Saya setuju dengan{" "}
|
Saya setuju dengan{" "}
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
@@ -126,11 +124,11 @@ export default function RegisterView() {
|
|||||||
Syarat & Ketentuan
|
Syarat & Ketentuan
|
||||||
</Text>{" "}
|
</Text>{" "}
|
||||||
yang melarang konten tidak pantas dan perilaku merugikan.
|
yang melarang konten tidak pantas dan perilaku merugikan.
|
||||||
</Text>
|
</Text> */}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
disabled={!term}
|
disabled={isLoading}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
onPress={handleRegister}
|
onPress={handleRegister}
|
||||||
>
|
>
|
||||||
|
|||||||
48
screens/Home/HeaderBell.tsx
Normal file
48
screens/Home/HeaderBell.tsx
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// components/HeaderBell.tsx
|
||||||
|
import { MainColor } from "@/constants/color-palet";
|
||||||
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
|
import { useNotificationStore } from "@/hooks/use-notification-store";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { Text, View } from "react-native";
|
||||||
|
|
||||||
|
export default function HeaderBell() {
|
||||||
|
const { unreadCount } = useNotificationStore();
|
||||||
|
const { user } = useAuth();
|
||||||
|
|
||||||
|
const pathDetector =
|
||||||
|
user?.masterUserRoleId === "1" ? "/notifications" : "/admin/notification";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{ position: "relative" }}>
|
||||||
|
<Ionicons
|
||||||
|
name="notifications"
|
||||||
|
size={20}
|
||||||
|
color={MainColor.yellow}
|
||||||
|
onPress={() => {
|
||||||
|
router.push(pathDetector);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -17,7 +17,12 @@ export default function Home_BottomFeatureSection() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// console.log("[DATA JOB]", JSON.stringify(response.data, null, 2));
|
// console.log("[DATA JOB]", JSON.stringify(response.data, null, 2));
|
||||||
const result = response.data.slice(-2);
|
const result = response.data
|
||||||
|
.sort(
|
||||||
|
(a: any, b: any) =>
|
||||||
|
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
|
||||||
|
)
|
||||||
|
.slice(0, 2);
|
||||||
setListData(result);
|
setListData(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("[ERROR]", error);
|
console.log("[ERROR]", error);
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
import { ITabs } from "@/components/_Interface/types";
|
import { ITabs } from "@/components/_Interface/types";
|
||||||
|
import { Platform } from "react-native";
|
||||||
|
|
||||||
export const tabsHome: any = ({acceptedForumTermsAt, profileId}: {acceptedForumTermsAt: Date, profileId: string}) => [
|
export const tabsHome: any = ({
|
||||||
|
acceptedForumTermsAt,
|
||||||
|
profileId,
|
||||||
|
}: {
|
||||||
|
acceptedForumTermsAt: Date;
|
||||||
|
profileId: string;
|
||||||
|
}) => [
|
||||||
{
|
{
|
||||||
id: "forum",
|
id: "forum",
|
||||||
icon: "chatbubble-ellipses-outline",
|
icon: "chatbubble-ellipses-outline",
|
||||||
activeIcon: "chatbubble-ellipses",
|
activeIcon: "chatbubble-ellipses",
|
||||||
label: "Forum",
|
label: "Forum",
|
||||||
path: acceptedForumTermsAt ? "/forum" : "/forum/terms",
|
// path: acceptedForumTermsAt ? "/forum" : "/forum/terms",
|
||||||
|
path: "/forum",
|
||||||
isActive: true,
|
isActive: true,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
},
|
},
|
||||||
@@ -25,8 +33,8 @@ export const tabsHome: any = ({acceptedForumTermsAt, profileId}: {acceptedForumT
|
|||||||
activeIcon: "map",
|
activeIcon: "map",
|
||||||
label: "Maps",
|
label: "Maps",
|
||||||
path: "/maps",
|
path: "/maps",
|
||||||
isActive: true,
|
isActive: Platform.OS === "ios" ? true : false,
|
||||||
disabled: false,
|
disabled: Platform.OS === "ios" ? false : true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "profile",
|
id: "profile",
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
TextCustom,
|
TextCustom,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import API_STRORAGE from "@/constants/base-url-api-strorage";
|
import API_STRORAGE from "@/constants/base-url-api-strorage";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
|
||||||
import DUMMY_IMAGE from "@/constants/dummy-image-value";
|
import DUMMY_IMAGE from "@/constants/dummy-image-value";
|
||||||
import { countDownAndCondition } from "@/utils/countDownAndCondition";
|
import { countDownAndCondition } from "@/utils/countDownAndCondition";
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
@@ -22,8 +21,6 @@ export default function Investment_BoxBerandaSection({
|
|||||||
id: string;
|
id: string;
|
||||||
data: any;
|
data: any;
|
||||||
}) {
|
}) {
|
||||||
// console.log("[DATA By one]", JSON.stringify(data, null, 2));
|
|
||||||
|
|
||||||
const [value, setValue] = useState({
|
const [value, setValue] = useState({
|
||||||
sisa: 0,
|
sisa: 0,
|
||||||
reminder: false,
|
reminder: false,
|
||||||
@@ -33,8 +30,6 @@ export default function Investment_BoxBerandaSection({
|
|||||||
updateCountDown();
|
updateCountDown();
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
console.log("[DATA BERANDA]", JSON.stringify(data, null, 2));
|
|
||||||
|
|
||||||
const updateCountDown = () => {
|
const updateCountDown = () => {
|
||||||
const countDown = countDownAndCondition({
|
const countDown = countDownAndCondition({
|
||||||
duration: data?.pencarianInvestor,
|
duration: data?.pencarianInvestor,
|
||||||
|
|||||||
@@ -1,16 +1,28 @@
|
|||||||
import { BaseBox, StackCustom, TextCustom, ProgressCustom } from "@/components";
|
import { BaseBox, StackCustom, TextCustom, ProgressCustom } from "@/components";
|
||||||
|
|
||||||
export default function Invesment_BoxProgressSection({progress, status}: {progress: number, status: string}) {
|
export default function Invesment_BoxProgressSection({
|
||||||
return (
|
progress,
|
||||||
<>
|
status,
|
||||||
{status === "publish" && (
|
}: {
|
||||||
<BaseBox>
|
progress: number;
|
||||||
<StackCustom>
|
status: string;
|
||||||
<TextCustom bold>Progress Saham</TextCustom>
|
}) {
|
||||||
<ProgressCustom label={(progress || 0) + "%"} value={progress || 0} size="lg" />
|
return (
|
||||||
</StackCustom>
|
<>
|
||||||
</BaseBox>
|
{status === "publish" && (
|
||||||
)}
|
<BaseBox>
|
||||||
</>
|
<StackCustom>
|
||||||
);
|
<TextCustom bold>Progress Saham</TextCustom>
|
||||||
|
<ProgressCustom
|
||||||
|
label={(progress || 0) + "%"}
|
||||||
|
value={progress || 0}
|
||||||
|
size="lg"
|
||||||
|
animated
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
</StackCustom>
|
||||||
|
</BaseBox>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -15,6 +15,7 @@ export default function AppRoot() {
|
|||||||
name="index"
|
name="index"
|
||||||
options={{ title: "", headerBackVisible: false }}
|
options={{ title: "", headerBackVisible: false }}
|
||||||
/>
|
/>
|
||||||
|
<Stack.Screen name="eula" options={{ title: "Terms & Conditions", headerBackVisible: false }} />
|
||||||
<Stack.Screen name="+not-found" options={{ title: "" }} />
|
<Stack.Screen name="+not-found" options={{ title: "" }} />
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="verification"
|
name="verification"
|
||||||
|
|||||||
@@ -57,9 +57,19 @@ export async function apiAdminForumListReportCommentById({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function apiAdminForumDeactivateComment({ id }: { id: string }) {
|
export async function apiAdminForumDeactivateComment({
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
data: { senderId: string };
|
||||||
|
}) {
|
||||||
|
|
||||||
|
console.log("data", data)
|
||||||
try {
|
try {
|
||||||
const response = await apiConfig.put(`/mobile/admin/forum/${id}/comment`);
|
const response = await apiConfig.put(`/mobile/admin/forum/${id}/comment`, {
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
@@ -81,9 +91,17 @@ export async function apiAdminForumListReportPostingById({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function apiAdminForumDeactivatePosting({ id }: { id: string }) {
|
export async function apiAdminForumDeactivatePosting({
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
data: { senderId: string };
|
||||||
|
}) {
|
||||||
try {
|
try {
|
||||||
const response = await apiConfig.put(`/mobile/admin/forum/${id}`);
|
const response = await apiConfig.put(`/mobile/admin/forum/${id}`, {
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { typeRejectedData } from "@/types/type-collect-other";
|
||||||
import { apiConfig } from "../api-config";
|
import { apiConfig } from "../api-config";
|
||||||
|
|
||||||
export async function apiAdminInvestment({
|
export async function apiAdminInvestment({
|
||||||
@@ -38,7 +39,7 @@ export async function apiAdminInvestasiUpdateByStatus({
|
|||||||
}: {
|
}: {
|
||||||
id: string;
|
id: string;
|
||||||
status: "publish" | "review" | "reject";
|
status: "publish" | "review" | "reject";
|
||||||
data: any;
|
data: typeRejectedData;
|
||||||
}) {
|
}) {
|
||||||
try {
|
try {
|
||||||
const response = await apiConfig.put(
|
const response = await apiConfig.put(
|
||||||
@@ -97,6 +98,7 @@ export async function apiAdminInvestmentUpdateInvoice({
|
|||||||
data: {
|
data: {
|
||||||
investasiId: string;
|
investasiId: string;
|
||||||
lembarTerbeli: number;
|
lembarTerbeli: number;
|
||||||
|
senderId: string
|
||||||
};
|
};
|
||||||
}) {
|
}) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -28,13 +28,15 @@ export const apiAdminUserAccessUpdateStatus = async ({
|
|||||||
id,
|
id,
|
||||||
active,
|
active,
|
||||||
role,
|
role,
|
||||||
|
category,
|
||||||
}: {
|
}: {
|
||||||
id: string;
|
id: string;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
role?: "user" | "admin" | "super_admin";
|
role?: "user" | "admin" | "super_admin";
|
||||||
|
category: "access" | "role";
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
try {
|
||||||
const response = await apiConfig.put(`/mobile/admin/user/${id}`, {
|
const response = await apiConfig.put(`/mobile/admin/user/${id}?category=${category}`, {
|
||||||
data: {
|
data: {
|
||||||
active,
|
active,
|
||||||
role,
|
role,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { typeRejectedData } from "@/types/type-collect-other";
|
||||||
import { apiConfig } from "../api-config";
|
import { apiConfig } from "../api-config";
|
||||||
|
|
||||||
export async function apiAdminVoting({
|
export async function apiAdminVoting({
|
||||||
@@ -32,7 +33,7 @@ export async function apiAdminVotingUpdateStatus({
|
|||||||
status,
|
status,
|
||||||
}: {
|
}: {
|
||||||
id: string;
|
id: string;
|
||||||
data?: string;
|
data?: typeRejectedData;
|
||||||
status: "publish" | "review" | "reject";
|
status: "publish" | "review" | "reject";
|
||||||
}) {
|
}) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -119,3 +119,62 @@ export async function apiForumDeleteComment({ id }: { id: string }) {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function apiForumGetReportPosting({id}: {id:string}) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.get(`/mobile/forum/${id}/preview-report-posting`);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiForumGetReportComment({id}: {id:string}) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.get(`/mobile/forum/${id}/preview-report-comment`);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function apiForumCreateReportPosting({
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
data: any;
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.post(
|
||||||
|
`/mobile/forum/${id}/report-posting`,
|
||||||
|
{
|
||||||
|
data: data,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiForumCreateReportCommentar({
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
data: any;
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.post(
|
||||||
|
`/mobile/forum/${id}/report-commentar`,
|
||||||
|
{
|
||||||
|
data: data,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -77,46 +77,6 @@ export async function apiMasterForumReportList() {
|
|||||||
|
|
||||||
// ================== END MASTER FORUM ================== //
|
// ================== END MASTER FORUM ================== //
|
||||||
|
|
||||||
export async function apiForumCreateReportPosting({
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
}: {
|
|
||||||
id: string;
|
|
||||||
data: any;
|
|
||||||
}) {
|
|
||||||
try {
|
|
||||||
const response = await apiConfig.post(
|
|
||||||
`/mobile/forum/${id}/report-posting`,
|
|
||||||
{
|
|
||||||
data: data,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function apiForumCreateReportCommentar({
|
|
||||||
id,
|
|
||||||
data,
|
|
||||||
}: {
|
|
||||||
id: string;
|
|
||||||
data: any;
|
|
||||||
}) {
|
|
||||||
try {
|
|
||||||
const response = await apiConfig.post(
|
|
||||||
`/mobile/forum/${id}/report-commentar`,
|
|
||||||
{
|
|
||||||
data: data,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ================== START MASTER INVESTMENT ================== //
|
// ================== START MASTER INVESTMENT ================== //
|
||||||
|
|
||||||
export async function apiMasterInvestment({
|
export async function apiMasterInvestment({
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user