Compare commits

...

26 Commits

Author SHA1 Message Date
676b8a38be Fix apple rejected:
-  app/(application)/(user)/delete-account.tsx
-  screens/Profile/menuDrawerSection.tsx

### No Issue
2025-11-20 15:42:37 +08:00
0a2aa71013 Add:
-  app/(application)/(user)/delete-account.tsx
-  assets/images/constants/logo-hipmi_back.png

Fix:
- app/(application)/(user)/_layout.tsx
- assets/images/constants/logo-hipmi.png
- components/Grid/GridCustom.tsx
- screens/Profile/ListPage.tsx
- screens/Profile/menuDrawerSection.tsx
- service/api-client/api-user.ts

### No Issue
2025-11-19 17:40:35 +08:00
868e96a54a Try to notification
### Issue: package import * as Notifications from expo-notifications;
2025-11-18 17:46:33 +08:00
059b4d053a Fix rejected apple delete account & start for notification
### No issue
2025-11-18 14:29:02 +08:00
76debfd6a6 Add:
-  google-services.json
- utils/notifications.ts

Fix:
- app.config.js : tambah access googleServicesFile
- app/_layout.tsx : tambah untuk push notifikasi
- package.json: install install expo-notifications expo-device expo-constants

### No Issue
2025-11-14 17:44:22 +08:00
8c3aec8e57 Admin Event: QR Code sudah bisa di scan
### No issue
2025-11-14 14:44:36 +08:00
1ade69ff2f Fix QR Code Access
### No Issue
2025-11-13 17:41:54 +08:00
97ea6ab799 1.0.1 2025-11-12 17:34:57 +08:00
4e9ce07759 Penambahan akses untuk QR COde pada file:
-  app.config.js
- service/api-config.ts

### No Issue
2025-11-12 17:34:35 +08:00
8f659c2b7e tambah repo 2025-11-12 14:06:55 +08:00
61bca7cfe1 tambah repo 2025-11-12 14:06:36 +08:00
5af85c3a8b tambah repo 2025-11-12 13:58:55 +08:00
a8807d88ad Staging & Change logo
### No Issue
2025-11-10 10:59:48 +08:00
5d36429aa4 Merge pull request 'Integrasi API' (#7) from api/4-nov-25 into main
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/7
2025-11-04 12:14:26 +08:00
ec49999f99 Integrasi API:
Add:
-  hipmi-note.md

Fix:
- app/(application)/(user)/donation/[id]/(transaction-flow)/[invoiceId]/failed.tsx
- app/(application)/(user)/donation/[id]/(transaction-flow)/[invoiceId]/success.tsx
- app/(application)/(user)/event/[id]/confirmation.tsx
- app/(application)/(user)/investment/(tabs)/index.tsx
- app/(application)/(user)/investment/(tabs)/my-holding.tsx
- app/(application)/(user)/investment/[id]/(my-holding)/[id].tsx
- app/(application)/(user)/investment/[id]/(transaction-flow)/failed.tsx
- app/(application)/(user)/investment/[id]/(transaction-flow)/index.tsx
- app/(application)/(user)/investment/[id]/(transaction-flow)/success.tsx
- app/(application)/(user)/investment/[id]/investor.tsx
- app/(application)/admin/investment/[id]/[status]/index.tsx
- app/(application)/admin/investment/[id]/[status]/transaction-detail.tsx
- app/(application)/admin/investment/[id]/list-of-investor.tsx
- lib/dummy-data/investment/dummy-data-not-publish.ts
- screens/Authentication/VerificationView.tsx
- screens/Home/bottomFeatureSection.tsx
- service/api-client/api-investment.ts

### No Issue
2025-11-04 12:13:49 +08:00
867e82c6fa Merge pull request 'Admin : Investasi integarsi API' (#6) from api-admin/31-oct-25 into main
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/6
2025-11-03 11:45:34 +08:00
f9f996f195 Admin : Investasi integarsi API
### NO Issue
2025-11-03 11:41:31 +08:00
98394309e6 Merge pull request 'Integrasi API: Investment & Admin Investment' (#5) from api-admin/30-oct-25 into main
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/5
2025-10-30 17:43:51 +08:00
4625831377 Integrasi API: Admin Investasi
Fix:
- app/(application)/(user)/investment/(tabs)/index.tsx
- app/(application)/admin/investment/[id]/[status]/transaction-detail.tsx
- app/(application)/admin/investment/[id]/list-of-investor.tsx
- screens/Invesment/BoxBerandaSection.tsx
- screens/Invesment/DetailDataPublishSection.tsx
- service/api-admin/api-admin-investment.ts

### No Issue
2025-10-30 17:36:42 +08:00
ebd6107c36 Integrasi API: Investment:
Add:
- screens/Invesment/BoxBerandaSection.tsx

Fix:
- app/(application)/(user)/investment/(tabs)/index.tsx
- screens/Donation/BoxPublish.tsx
- screens/Invesment/BoxProgressSection.tsx
- screens/Invesment/DetailDataPublishSection.tsx

### No Issue
2025-10-30 16:38:24 +08:00
f23cfe1107 Integrasi API: Investment & Admin Investment
Add:
- components/_ShareComponent/NoDataText.tsx
- service/api-admin/api-admin-investment.ts

Fix:
- app/(application)/(user)/investment/(tabs)/index.tsx
- app/(application)/admin/investment/[id]/[status]/index.tsx
- app/(application)/admin/investment/[id]/reject-input.tsx
- app/(application)/admin/investment/[status]/status.tsx
- app/(application)/admin/investment/index.tsx
- screens/Invesment/DetailDataPublishSection.tsx

### No Issue
2025-10-30 15:13:33 +08:00
f9d9b5fbaa Merge pull request 'Integrasi API: Donation & Admin Donation' (#4) from api-admin/29-oct-25 into main
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/4
2025-10-29 17:38:03 +08:00
b3209dc7ee Integrasi API: Donation & Admin Donation
Fix:
- app/(application)/(user)/donation/[id]/fund-disbursement.tsx
- app/(application)/(user)/donation/[id]/list-of-donatur.tsx
- app/(application)/admin/donation/[id]/[status]/index.tsx
- app/(application)/admin/donation/[id]/detail-disbursement-of-funds.tsx
- app/(application)/admin/donation/[id]/disbursement-of-funds.tsx
- app/(application)/admin/donation/[id]/list-disbursement-of-funds.tsx
- service/api-admin/api-admin-donation.ts
- service/api-client/api-donation.ts
- utils/pickFile.ts: Sudah bisa memilih ukuran crop tapi hanya di android

### No issue
2025-10-29 17:35:18 +08:00
31c1b35173 Merge pull request 'Integrasi API: Donation & Admin Donation' (#3) from api-admin/28-oct-25 into main
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/3
2025-10-28 17:51:23 +08:00
de0280367f Merge pull request 'Integrasi API: Donation Admin' (#2) from api-admin/27-oct-25 into main
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/2
2025-10-28 10:21:39 +08:00
c8b14b816f Merge pull request 'New repo mobile after delete !' (#1) from api/24-oct-25 into main
Reviewed-on: http://wibugit.wibudev.com/wibu/hipmi-mobile/pulls/1
2025-10-27 11:32:15 +08:00
111 changed files with 5916 additions and 801 deletions

View File

@@ -92,8 +92,8 @@ android {
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 1 versionCode 2
versionName "1.0.0" versionName "1.0.1"
buildConfigField "String", "REACT_NATIVE_RELEASE_LEVEL", "\"${findProperty('reactNativeReleaseLevel') ?: 'stable'}\"" buildConfigField "String", "REACT_NATIVE_RELEASE_LEVEL", "\"${findProperty('reactNativeReleaseLevel') ?: 'stable'}\""
} }
@@ -180,3 +180,5 @@ dependencies {
implementation jscFlavor implementation jscFlavor
} }
} }
apply plugin: 'com.google.gms.google-services'

View File

@@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "608461535079",
"project_id": "hipmi-badung-connect",
"storage_bucket": "hipmi-badung-connect.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:608461535079:android:4ff12ddc283fb3746761c2",
"android_client_info": {
"package_name": "com.bip.hipmimobileapp"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyBiDtIk3Q9zffFwIdJ5cjqY7e4390JGSkM"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

View File

@@ -29,6 +29,12 @@
<data android:scheme="hipmimobile"/> <data android:scheme="hipmimobile"/>
<data android:scheme="exp+hipmi-mobile"/> <data android:scheme="exp+hipmi-mobile"/>
</intent-filter> </intent-filter>
<intent-filter android:autoVerify="true" data-generated="true">
<action android:name="android.intent.action.VIEW"/>
<data android:scheme="https" android:host="cld-dkr-staging-hipmi.wibudev.com" android:pathPrefix="/"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity> </activity>
</application> </application>
</manifest> </manifest>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -1,5 +1,5 @@
<resources> <resources>
<string name="app_name">HIPMI BADUNG</string> <string name="app_name">HIPMI Badung Connect</string>
<string name="expo_system_ui_user_interface_style" translatable="false">automatic</string> <string name="expo_system_ui_user_interface_style" translatable="false">automatic</string>
<string name="expo_splash_screen_resize_mode" translatable="false">contain</string> <string name="expo_splash_screen_resize_mode" translatable="false">contain</string>
<string name="expo_splash_screen_status_bar_translucent" translatable="false">false</string> <string name="expo_splash_screen_status_bar_translucent" translatable="false">false</string>

View File

@@ -6,6 +6,7 @@ buildscript {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
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')

View File

@@ -31,7 +31,7 @@ extensions.configure(com.facebook.react.ReactSettingsExtension) { ex ->
} }
expoAutolinking.useExpoModules() expoAutolinking.useExpoModules()
rootProject.name = 'HIPMI BADUNG' rootProject.name = 'HIPMI Badung Connect'
expoAutolinking.useExpoVersionCatalog() expoAutolinking.useExpoVersionCatalog()

View File

@@ -1,61 +1,80 @@
// app.config.js // app.config.js
require('dotenv').config(); require("dotenv").config();
export default { export default {
name: 'HIPMI BADUNG', name: "HIPMI Badung Connect",
slug: 'hipmi-mobile', slug: "hipmi-mobile",
version: '1.0.0', version: "1.0.1",
orientation: 'portrait', orientation: "portrait",
icon: './assets/images/icon.png', icon: "./assets/images/icon.png",
scheme: 'hipmimobile', scheme: "hipmimobile",
userInterfaceStyle: 'automatic', userInterfaceStyle: "automatic",
newArchEnabled: true, newArchEnabled: true,
ios: { ios: {
supportsTablet: true, supportsTablet: true,
bundleIdentifier: 'com.anonymous.hipmi-mobile', bundleIdentifier: "com.anonymous.hipmi-mobile",
infoPlist: { infoPlist: {
ITSAppUsesNonExemptEncryption: false, ITSAppUsesNonExemptEncryption: false,
}, },
associatedDomains: ["applinks:cld-dkr-staging-hipmi.wibudev.com"],
buildNumber: "7",
}, },
android: { android: {
googleServicesFile: "./google-services.json",
adaptiveIcon: { adaptiveIcon: {
foregroundImage: './assets/images/splash-icon.png', foregroundImage: "./assets/images/splash-icon.png",
backgroundColor: '#ffffff', backgroundColor: "#ffffff",
}, },
edgeToEdgeEnabled: true, edgeToEdgeEnabled: true,
package: 'com.bip.hipmimobileapp', package: "com.bip.hipmimobileapp",
versionCode: 2,
// softwareKeyboardLayoutMode: 'resize', // option: untuk mengatur keyboard pada room chst collaboration // softwareKeyboardLayoutMode: 'resize', // option: untuk mengatur keyboard pada room chst collaboration
intentFilters: [
{
action: "VIEW",
autoVerify: true, // wajib untuk App Links
data: [
{
scheme: "https",
host: "cld-dkr-staging-hipmi.wibudev.com",
pathPrefix: "/",
},
],
category: ["BROWSABLE", "DEFAULT"],
},
],
}, },
web: { web: {
bundler: 'metro', bundler: "metro",
output: 'static', output: "static",
favicon: './assets/images/favicon.png', favicon: "./assets/images/favicon.png",
}, },
plugins: [ plugins: [
'expo-router', "expo-router",
'expo-web-browser', "expo-notifications",
"expo-web-browser",
[ [
'expo-splash-screen', "expo-splash-screen",
{ {
image: './assets/images/splash-icon.png', image: "./assets/images/splash-icon.png",
imageWidth: 200, imageWidth: 200,
resizeMode: 'contain', resizeMode: "contain",
backgroundColor: '#ffffff', backgroundColor: "#ffffff",
}, },
], ],
[ [
'expo-camera', "expo-camera",
{ {
cameraPermission: 'Allow $(PRODUCT_NAME) to access your camera', cameraPermission: "Allow $(PRODUCT_NAME) to access your camera",
microphonePermission: 'Allow $(PRODUCT_NAME) to access your microphone', microphonePermission: "Allow $(PRODUCT_NAME) to access your microphone",
recordAudioAndroid: true, recordAudioAndroid: true,
}, },
], ],
'expo-font', "expo-font",
], ],
experiments: { experiments: {
@@ -65,7 +84,7 @@ export default {
extra: { extra: {
router: {}, router: {},
eas: { eas: {
projectId: '5cf15964-4889-4755-b8ed-b99c61d614d1', projectId: "5cf15964-4889-4755-b8ed-b99c61d614d1",
}, },
// Tambahkan environment variables ke sini // Tambahkan environment variables ke sini
API_BASE_URL: process.env.API_BASE_URL, API_BASE_URL: process.env.API_BASE_URL,

View File

@@ -10,6 +10,13 @@ export default function UserLayout() {
return ( return (
<> <>
<Stack screenOptions={HeaderStyles}> <Stack screenOptions={HeaderStyles}>
<Stack.Screen
name="delete-account"
options={{
title: "Hapus Akun",
headerLeft: () => <BackButton />,
}}
/>
<Stack.Screen <Stack.Screen
name="waiting-room" name="waiting-room"
options={{ options={{

View File

@@ -0,0 +1,111 @@
import {
AlertDefaultSystem,
BaseBox,
ButtonCustom,
CenterCustom,
StackCustom,
TextCustom,
TextInputCustom,
ViewWrapper,
} from "@/components";
import { useAuth } from "@/hooks/use-auth";
import { apiDeleteUser } from "@/service/api-client/api-user";
import { Image } from "expo-image";
import { useLocalSearchParams } from "expo-router/build/hooks";
import { useState } from "react";
import Toast from "react-native-toast-message";
export default function DeleteAccount() {
const { token, logout, user } = useAuth();
const { phone } = useLocalSearchParams();
const [text, setText] = useState("");
const [isLoading, setLoading] = useState(false);
const deleteAccount = async () => {
if (text !== "Delete Account") {
return Toast.show({
type: "error",
text1: "Ketik 'Delete Account' untuk menghapus akun",
});
}
AlertDefaultSystem({
title: "Anda yakin akan menghapus akun ini?",
message:
"Semua data yang pernah anda buat akan terhapus secara permanen !",
textLeft: "Batal",
textRight: "Ya",
onPressRight: async () => {
try {
setLoading(true);
const response = await apiDeleteUser({ id: user?.id as string });
if (response.success) {
console.log("RESPONSE >> ", response);
Toast.show({
type: "success",
text1: "Akun berhasil dihapus",
});
setTimeout(() => {
logout();
setLoading(false);
}, 2000);
} else {
Toast.show({
type: "error",
text1: "Gagal menghapus akun",
});
setLoading(false);
}
} catch (error) {
console.log("ERROR >> ", error);
setLoading(false);
}
},
});
};
return (
<>
<ViewWrapper>
<StackCustom>
<BaseBox>
<StackCustom>
<CenterCustom>
<Image
source={require("@/assets/images/constants/logo-hipmi.png")}
style={{
width: 150,
height: 150,
}}
/>
</CenterCustom>
<TextCustom align="center">
Anda akan menghapus akun dengan nomor +{phone}
</TextCustom>
<TextCustom align="center">
Ketik 'Delete Account' untuk menghapus akun
</TextCustom>
<TextInputCustom
value={text}
onChangeText={setText}
placeholder="Ketik 'Delete Account'"
/>
<ButtonCustom
backgroundColor="red"
textColor="white"
onPress={deleteAccount}
isLoading={isLoading}
disabled={isLoading}
>
Submit
</ButtonCustom>
</StackCustom>
</BaseBox>
</StackCustom>
</ViewWrapper>
</>
);
}

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
BaseBox, BaseBox,
Grid, Grid,
@@ -7,11 +8,60 @@ import {
ViewWrapper, ViewWrapper,
} from "@/components"; } from "@/components";
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
import { apiDonationGetInvoiceById } from "@/service/api-client/api-donation";
import { GStyles } from "@/styles/global-styles"; import { GStyles } from "@/styles/global-styles";
import { dateTimeView } from "@/utils/dateTimeView";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import { FontAwesome6 } from "@expo/vector-icons"; import { FontAwesome6 } from "@expo/vector-icons";
import dayjs from "dayjs"; import { useFocusEffect, useLocalSearchParams } from "expo-router";
import { useCallback, useState } from "react";
export default function DonasiFailed() { export default function DonasiFailed() {
const { id, invoiceId } = useLocalSearchParams();
const [data, setData] = useState<any>(null);
useFocusEffect(
useCallback(() => {
onLoadData();
}, [id, invoiceId])
);
const onLoadData = async () => {
try {
const response = await apiDonationGetInvoiceById({
id: invoiceId as string,
});
console.log("[DATA]", JSON.stringify(response.data, null, 2));
setData(response.data);
} catch (error) {
console.log("[ERROR]", error);
}
};
const listData = [
{
label: "Bank",
value: (data && data?.MasterBank?.namaBank) || "-",
},
{
label: "Rekening Penerima",
value: (data && data?.MasterBank?.namaAkun) || "-",
},
{
label: "No Rekening",
value: (data && data?.MasterBank?.norek) || "-",
},
{
label: "Jumlah Donasi",
value: (data && formatCurrencyDisplay(data?.nominal)) || "-",
},
{
label: "Tanggal",
value: (data && dateTimeView({ date: data?.createdAt })) || "-",
},
];
return ( return (
<ViewWrapper> <ViewWrapper>
<StackCustom> <StackCustom>
@@ -58,26 +108,3 @@ export default function DonasiFailed() {
</ViewWrapper> </ViewWrapper>
); );
} }
const listData = [
{
label: "Bank",
value: " BCA",
},
{
label: "Rekening Penerima",
value: "Himpunan Pengusaha Muda Indonesia",
},
{
label: "No Rekening",
value: "2304235678854332",
},
{
label: "Jumlah Donasi",
value: "Rp. 750.000",
},
{
label: "Tanggal",
value: `${dayjs(new Date()).format("DD/MM/YYYY")}`,
},
];

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
BaseBox, BaseBox,
Grid, Grid,
@@ -7,11 +8,60 @@ import {
ViewWrapper, ViewWrapper,
} from "@/components"; } from "@/components";
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
import { apiDonationGetInvoiceById } from "@/service/api-client/api-donation";
import { GStyles } from "@/styles/global-styles"; import { GStyles } from "@/styles/global-styles";
import { dateTimeView } from "@/utils/dateTimeView";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import { FontAwesome6 } from "@expo/vector-icons"; import { FontAwesome6 } from "@expo/vector-icons";
import dayjs from "dayjs"; import { useFocusEffect, useLocalSearchParams } from "expo-router";
import { useCallback, useState } from "react";
export default function DonationSuccess() { export default function DonationSuccess() {
const { id, invoiceId } = useLocalSearchParams();
const [data, setData] = useState<any>(null);
useFocusEffect(
useCallback(() => {
onLoadData();
}, [id, invoiceId])
);
const onLoadData = async () => {
try {
const response = await apiDonationGetInvoiceById({
id: invoiceId as string,
});
console.log("[DATA]", JSON.stringify(response.data, null, 2));
setData(response.data);
} catch (error) {
console.log("[ERROR]", error);
}
};
const listData = [
{
label: "Bank",
value: (data && data?.MasterBank?.namaBank) || "-",
},
{
label: "Rekening Penerima",
value: (data && data?.MasterBank?.namaAkun) || "-",
},
{
label: "No Rekening",
value: (data && data?.MasterBank?.norek) || "-",
},
{
label: "Jumlah Donasi",
value: (data && formatCurrencyDisplay(data?.nominal)) || "-",
},
{
label: "Tanggal",
value: (data && dateTimeView({ date: data?.createdAt })) || "-",
},
];
return ( return (
<ViewWrapper> <ViewWrapper>
<StackCustom> <StackCustom>
@@ -59,25 +109,4 @@ export default function DonationSuccess() {
); );
} }
const listData = [
{
label: "Bank",
value: " BCA",
},
{
label: "Rekening Penerima",
value: "Himpunan Pengusaha Muda Indonesia",
},
{
label: "No Rekening",
value: "2304235678854332",
},
{
label: "Jumlah Donasi",
value: "Rp. 750.000",
},
{
label: "Tanggal",
value: `${dayjs(new Date()).format("DD/MM/YYYY")}`,
},
];

View File

@@ -1,17 +1,71 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
BaseBox, BaseBox,
ButtonCenteredOnly, ButtonCenteredOnly,
Grid, Grid,
InformationBox, InformationBox,
LoaderCustom,
StackCustom, StackCustom,
TextCustom, TextCustom,
ViewWrapper, ViewWrapper,
} from "@/components"; } from "@/components";
import {
apiDonationDisbursementOfFundsListById,
apiDonationGetOne,
} from "@/service/api-client/api-donation";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { router, useLocalSearchParams } from "expo-router"; import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash";
import React, { useState } from "react";
export default function DonationFundDisbursement() { export default function DonationFundDisbursement() {
const { id } = useLocalSearchParams(); const { id } = useLocalSearchParams();
const [data, setData] = useState({
totalPencairan: 0,
akumulasiPencairan: 0,
});
const [listData, setListData] = React.useState<any[] | null>(null);
const [loadData, setLoadData] = React.useState(false);
useFocusEffect(
React.useCallback(() => {
onLoadData();
}, [id])
);
const onLoadData = async () => {
try {
setLoadData(true);
const responseData = await apiDonationGetOne({
id: id as string,
category: "permanent",
});
if (responseData.success) {
setData({
totalPencairan: responseData.data.totalPencairan,
akumulasiPencairan: responseData.data.akumulasiPencairan,
});
}
const responseList = await apiDonationDisbursementOfFundsListById({
id: id as string,
});
if (responseList.success) {
setListData(responseList.data);
}
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadData(false);
}
};
return ( return (
<> <>
<ViewWrapper> <ViewWrapper>
@@ -20,39 +74,41 @@ export default function DonationFundDisbursement() {
<Grid> <Grid>
<Grid.Col span={6}> <Grid.Col span={6}>
<TextCustom bold color="yellow"> <TextCustom bold color="yellow">
Rp. 0 Rp. {formatCurrencyDisplay(data?.totalPencairan)}
</TextCustom> </TextCustom>
<TextCustom size="small">Total Pencairan Dana</TextCustom> <TextCustom size="small">Total Pencairan Dana</TextCustom>
</Grid.Col> </Grid.Col>
<Grid.Col span={6}> <Grid.Col span={6}>
<TextCustom bold color="yellow"> <TextCustom bold color="yellow">
0 kali {data?.akumulasiPencairan} kali
</TextCustom> </TextCustom>
<TextCustom size="small">Akumulasi Pencairan</TextCustom> <TextCustom size="small">Akumulasi Pencairan</TextCustom>
</Grid.Col> </Grid.Col>
</Grid> </Grid>
</BaseBox> </BaseBox>
{Array.from({ length: 10 }).map((_, index) => ( {loadData ? (
<LoaderCustom />
) : _.isEmpty(listData) ? (
<TextCustom align="center" color="gray">
Belum ada data
</TextCustom>
) : (
listData?.map((item, index) => (
<BaseBox key={index}> <BaseBox key={index}>
<StackCustom> <StackCustom>
<Grid> <Grid>
<Grid.Col span={8}> <Grid.Col span={8}>
<TextCustom bold>Pencairan ke - {index + 1}</TextCustom> <TextCustom bold>{item?.title}</TextCustom>
</Grid.Col> </Grid.Col>
<Grid.Col span={4} style={{ alignItems: "flex-end" }}> <Grid.Col span={4} style={{ alignItems: "flex-end" }}>
<TextCustom>{dayjs().format("DD MMM YYYY")}</TextCustom> <TextCustom>{dayjs(item?.createdAt).format("DD MMM YYYY")}</TextCustom>
</Grid.Col> </Grid.Col>
</Grid> </Grid>
<TextCustom> <TextCustom>{item?.deskripsi}</TextCustom>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Nesciunt dolor ad sit? Eaque rem nihil natus, id, esse possimus
perferendis provident velit illo consectetur distinctio ab
accusantium quis earum omnis!
</TextCustom>
<ButtonCenteredOnly <ButtonCenteredOnly
onPress={() => { onPress={() => {
router.navigate(`/(application)/(file)/${id}`); router.navigate(`/(application)/(image)/preview-image/${item?.imageId}`);
}} }}
icon="file-text" icon="file-text"
> >
@@ -60,7 +116,8 @@ export default function DonationFundDisbursement() {
</ButtonCenteredOnly> </ButtonCenteredOnly>
</StackCustom> </StackCustom>
</BaseBox> </BaseBox>
))} ))
)}
</ViewWrapper> </ViewWrapper>
</> </>
); );

View File

@@ -1,19 +1,62 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
BaseBox, BaseBox,
Grid, Grid,
LoaderCustom,
Spacing,
StackCustom, StackCustom,
TextCustom, TextCustom,
ViewWrapper, ViewWrapper,
} from "@/components"; } from "@/components";
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
import { apiAdminDonationListOfDonaturById } from "@/service/api-admin/api-admin-donation";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import { FontAwesome6 } from "@expo/vector-icons"; import { FontAwesome6 } from "@expo/vector-icons";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash";
import { useCallback, useState } from "react";
export default function Donation_ListOfDonatur() { export default function Donation_ListOfDonatur() {
const { id } = useLocalSearchParams();
const [listData, setListData] = useState<any[] | null>(null);
const [loadData, setLoadData] = useState(false);
useFocusEffect(
useCallback(() => {
onLoadData();
}, [id])
);
const onLoadData = async () => {
try {
setLoadData(true);
const response = await apiAdminDonationListOfDonaturById({
id: id as string,
});
if (response.success) {
setListData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadData(false);
}
};
return ( return (
<> <>
<ViewWrapper> <ViewWrapper>
{Array.from({ length: 10 }).map((_, index) => ( {loadData ? (
<LoaderCustom />
) : _.isEmpty(listData) ? (
<TextCustom bold align="center">
Belum ada donatur
</TextCustom>
) : (
listData?.map((item: any, index: number) => (
<BaseBox key={index}> <BaseBox key={index}>
<Grid> <Grid>
<Grid.Col <Grid.Col
@@ -27,20 +70,24 @@ export default function Donation_ListOfDonatur() {
/> />
</Grid.Col> </Grid.Col>
<Grid.Col span={9}> <Grid.Col span={9}>
<StackCustom gap={"xs"}>
<TextCustom bold size="large"> <TextCustom bold size="large">
Username {item?.Author?.username || "-"}
</TextCustom> </TextCustom>
<TextCustom>Berdonas sebesar </TextCustom> <Spacing/>
<StackCustom gap={"xs"}>
<TextCustom size={"small"}>Berdonas sebesar </TextCustom>
<TextCustom bold size="large" color="yellow"> <TextCustom bold size="large" color="yellow">
Rp. 100.000 Rp. {formatCurrencyDisplay(item?.nominal)}
</TextCustom>
<TextCustom>
{dayjs(item?.createdAt).format("DD MMM YYYY, HH:mm")}
</TextCustom> </TextCustom>
<TextCustom>{dayjs().format("DD MMM YYYY")}</TextCustom>
</StackCustom> </StackCustom>
</Grid.Col> </Grid.Col>
</Grid> </Grid>
</BaseBox> </BaseBox>
))} ))
)}
</ViewWrapper> </ViewWrapper>
</> </>
); );

View File

@@ -261,16 +261,16 @@ export default function UserEventConfirmation() {
<Stack.Screen <Stack.Screen
options={{ options={{
title: "Konfirmasi Event", title: "Konfirmasi Event",
headerLeft: () => ( // headerLeft: () => (
<Ionicons // <Ionicons
name="arrow-back" // name="arrow-back"
size={20} // size={20}
color={MainColor.yellow} // color={MainColor.yellow}
onPress={() => // onPress={() =>
router.navigate("/(application)/(user)/event/create") // router.navigate("/(application)/(user)/event/create")
} // }
/> // />
), // ),
}} }}
/> />
<ViewWrapper>{handlerReturn()}</ViewWrapper> <ViewWrapper>{handlerReturn()}</ViewWrapper>

View File

@@ -1,23 +1,14 @@
import { import {
BaseBox,
FloatingButton, FloatingButton,
Grid,
LoaderCustom, LoaderCustom,
ProgressCustom, ViewWrapper
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components"; } from "@/components";
import API_STRORAGE from "@/constants/base-url-api-strorage"; import NoDataText from "@/components/_ShareComponent/NoDataText";
import DUMMY_IMAGE from "@/constants/dummy-image-value"; import Investment_BoxBerandaSection from "@/screens/Invesment/BoxBerandaSection";
import { apiInvestmentGetAll } from "@/service/api-client/api-investment"; import { apiInvestmentGetAll } from "@/service/api-client/api-investment";
import { Ionicons } from "@expo/vector-icons";
import dayjs from "dayjs";
import { Image } from "expo-image";
import { router, useFocusEffect } from "expo-router"; import { router, useFocusEffect } from "expo-router";
import _ from "lodash"; import _ from "lodash";
import { useCallback, useState } from "react"; import { useCallback, useState } from "react";
import { View } from "react-native";
export default function InvestmentBursa() { export default function InvestmentBursa() {
const [list, setList] = useState<any[] | null>(null); const [list, setList] = useState<any[] | null>(null);
@@ -32,8 +23,10 @@ export default function InvestmentBursa() {
const onLoadList = async () => { const onLoadList = async () => {
try { try {
setLoadingList(true); setLoadingList(true);
const response = await apiInvestmentGetAll(); const response = await apiInvestmentGetAll({
console.log("[DATA LIST]", JSON.stringify(response.data, null, 2)); category: "bursa"
});
// console.log("[DATA LIST]", JSON.stringify(response.data, null, 2));
setList(response.data); setList(response.data);
} catch (error) { } catch (error) {
console.log("[ERROR]", error); console.log("[ERROR]", error);
@@ -52,95 +45,12 @@ export default function InvestmentBursa() {
{loadingList ? ( {loadingList ? (
<LoaderCustom /> <LoaderCustom />
) : _.isEmpty(list) ? ( ) : _.isEmpty(list) ? (
<TextCustom>Belum ada data</TextCustom> <NoDataText />
) : ( ) : (
list?.map((item: any, index: number) => ( list?.map((item: any, index: number) => (
<BaseBox <Investment_BoxBerandaSection id={item.id} data={item} key={index} />
key={index}
paddingTop={7}
paddingBottom={7}
href={`/investment/${item.id}`}
>
<Grid>
<Grid.Col span={5}>
<Image
source={
item && item.imageId
? API_STRORAGE.GET({ fileId: item.imageId })
: DUMMY_IMAGE.background
}
style={{ width: "auto", height: 100, borderRadius: 10 }}
/>
</Grid.Col>
<Grid.Col span={1}>
<View />
</Grid.Col>
<Grid.Col span={6}>
<StackCustom>
<TextCustom truncate={2}>{item.title}</TextCustom>
<ProgressCustom
label={`${item.progress}%`}
value={item.progress}
size="lg"
/>
{Number(item?.pencarianInvestor) -
dayjs().diff(dayjs(item.countDown), "days") <=
0 ? (
<View
style={{
flexDirection: "row",
alignItems: "center",
gap: 5,
}}
>
<Ionicons
name="alert-circle-outline"
size={16}
color="red"
/>
<TextCustom color="red" size="small">
Periode Investasi Selesai
</TextCustom>
</View>
) : (
<TextCustom>
Sisa waktu:{" "}
{Number(item?.pencarianInvestor) -
dayjs().diff(dayjs(item.countDown), "days")}{" "}
hari
</TextCustom>
)}
</StackCustom>
</Grid.Col>
</Grid>
</BaseBox>
)) ))
)} )}
</ViewWrapper> </ViewWrapper>
); );
} }
// <View style={{ padding: 20, gap: 16 }}>
// <TextCustom>Progress 70%</TextCustom>
// <ProgressCustom value={70} color="primary" size="md" />
// <TextCustom>Success Progress</TextCustom>
// <ProgressCustom value={40} color="success" size="lg" />
// <TextCustom>Warning Progress (small)</TextCustom>
// <ProgressCustom value={90} color="warning" size="sm" />
// <TextCustom>Error Indeterminate</TextCustom>
// <ProgressCustom value={null} color="error" size="md" />
// <TextCustom>Custom Radius</TextCustom>
// <ProgressCustom value={60} color="info" size="xl" radius={4} />
// <ProgressCustom value={70} color="primary" size="lg" />
// <ProgressCustom value={45} color="success" size="md" label="Halfway!" />
// <ProgressCustom value={90} color="warning" size="lg" showLabel={false} />
// <ProgressCustom value={null} color="error" size="sm" label="Loading..." />
// </View>;

View File

@@ -1,33 +1,80 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
BaseBox, BaseBox,
Grid, Grid,
LoaderCustom,
ProgressCustom, ProgressCustom,
Spacing, Spacing,
StackCustom, StackCustom,
TextCustom, TextCustom,
ViewWrapper, ViewWrapper,
} from "@/components"; } from "@/components";
import { router } from "expo-router"; import NoDataText from "@/components/_ShareComponent/NoDataText";
import { useAuth } from "@/hooks/use-auth";
import {
apiInvestmentGetAll
} from "@/service/api-client/api-investment";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import { router, useFocusEffect } from "expo-router";
import _ from "lodash";
import React, { useCallback, useState } from "react";
import { View } from "react-native"; import { View } from "react-native";
export default function InvestmentMyHolding() { export default function InvestmentMyHolding() {
const { user } = useAuth();
const [list, setList] = useState<any[] | null>(null);
const [loadingList, setLoadingList] = useState(false);
useFocusEffect(
useCallback(() => {
onLoadList();
}, [user?.id])
);
const onLoadList = async () => {
try {
setLoadingList(true);
const response = await apiInvestmentGetAll({
category: "my-holding",
authorId: user?.id,
});
console.log("[DATA LIST]", JSON.stringify(response.data, null, 2));
setList(response.data);
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadingList(false);
}
};
return ( return (
<ViewWrapper hideFooter> <ViewWrapper hideFooter>
{Array.from({ length: 10 }).map((_, index) => ( {loadingList ? (
<BaseBox key={index} paddingTop={7} paddingBottom={7} onPress={() => router.push(`/investment/${index}/(my-holding)/holding-${index}`)}> <LoaderCustom />
) : _.isEmpty(list) ? (
<NoDataText />
) : (
list?.map((item, index) => (
<BaseBox
key={index}
paddingTop={7}
paddingBottom={7}
onPress={() =>
router.push(`/investment/${item?.id}/(my-holding)/${item?.id}`)
}
>
<Grid> <Grid>
<Grid.Col span={6}> <Grid.Col span={6}>
<StackCustom gap={"xs"}> <StackCustom gap={"xs"}>
<TextCustom truncate={2}> <TextCustom truncate={2}>{item?.title}</TextCustom>
Title here : Lorem ipsum dolor sit amet consectetur
adipisicing elit. Omnis, exercitationem, sequi enim quod
distinctio maiores laudantium amet, quidem atque repellat sit
vitae qui aliquam est veritatis laborum eum voluptatum totam!
</TextCustom>
<Spacing height={5} /> <Spacing height={5} />
<TextCustom size="small">Rp. 7.500.000</TextCustom> <TextCustom size="small">
<TextCustom size="small">300 Lembar</TextCustom> Rp. {formatCurrencyDisplay(item?.nominal)}
</TextCustom>
<TextCustom size="small">
{item?.lembarTerbeli} Lembar
</TextCustom>
</StackCustom> </StackCustom>
</Grid.Col> </Grid.Col>
<Grid.Col span={1}> <Grid.Col span={1}>
@@ -40,11 +87,16 @@ export default function InvestmentMyHolding() {
alignItems: "center", alignItems: "center",
}} }}
> >
<ProgressCustom value={(index % 5) * 20} size="lg" /> <ProgressCustom
value={item?.progress}
label={`${item?.progress}%`}
size="lg"
/>
</Grid.Col> </Grid.Col>
</Grid> </Grid>
</BaseBox> </BaseBox>
))} ))
)}
</ViewWrapper> </ViewWrapper>
); );
} }

View File

@@ -8,6 +8,7 @@ import {
TextCustom, TextCustom,
ViewWrapper, ViewWrapper,
} from "@/components"; } from "@/components";
import NoDataText from "@/components/_ShareComponent/NoDataText";
import { useAuth } from "@/hooks/use-auth"; import { useAuth } from "@/hooks/use-auth";
import { apiInvestmentGetInvoice } from "@/service/api-client/api-investment"; import { apiInvestmentGetInvoice } from "@/service/api-client/api-investment";
import { GStyles } from "@/styles/global-styles"; import { GStyles } from "@/styles/global-styles";
@@ -74,7 +75,7 @@ export default function InvestmentTransaction() {
{loadList ? ( {loadList ? (
<LoaderCustom /> <LoaderCustom />
) : _.isEmpty(list) ? ( ) : _.isEmpty(list) ? (
<TextCustom>Tidak ada data</TextCustom> <NoDataText/>
) : ( ) : (
list.map((item: any, i: number) => ( list.map((item: any, i: number) => (
<BaseBox <BaseBox

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
BackButton, BackButton,
BaseBox, BaseBox,
@@ -13,17 +14,43 @@ import { IconDocument, IconEdit, IconNews } from "@/components/_Icon";
import { IMenuDrawerItem } from "@/components/_Interface/types"; import { IMenuDrawerItem } from "@/components/_Interface/types";
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value"; import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
import { useAuth } from "@/hooks/use-auth";
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 { apiInvestmentGetInvoice } from "@/service/api-client/api-investment";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import { AntDesign, MaterialIcons } from "@expo/vector-icons"; import { AntDesign, MaterialIcons } from "@expo/vector-icons";
import { router, Stack, useLocalSearchParams } from "expo-router"; import { router, Stack, useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash"; import _ from "lodash";
import { useState } from "react"; import { useCallback, useState } from "react";
export default function InvestmentDetailHolding() { export default function InvestmentDetailHolding() {
const { user } = useAuth();
const { id, status } = useLocalSearchParams(); const { id, status } = useLocalSearchParams();
const [openDrawerDraft, setOpenDrawerDraft] = useState(false); const [openDrawerDraft, setOpenDrawerDraft] = useState(false);
const [openDrawerPublish, setOpenDrawerPublish] = useState(false); const [openDrawerPublish, setOpenDrawerPublish] = useState(false);
const [data, setData] = useState<any>(null);
useFocusEffect(
useCallback(() => {
onLoadData();
}, [id, status])
);
const onLoadData = async () => {
try {
const response = await apiInvestmentGetInvoice({
id: id as string,
authorId: user?.id,
category: "invoice",
});
console.log("[DATA]", JSON.stringify(response.data, null, 2));
setData(response.data);
} catch (error) {
console.log("[ERROR]", error);
}
};
const handlePressDraft = (item: IMenuDrawerItem) => { const handlePressDraft = (item: IMenuDrawerItem) => {
console.log("PATH >> ", item.path); console.log("PATH >> ", item.path);
@@ -39,7 +66,8 @@ export default function InvestmentDetailHolding() {
const bottomSection = ( const bottomSection = (
<Invesment_ComponentBoxOnBottomDetail <Invesment_ComponentBoxOnBottomDetail
id={id as string} prospectusId={id as string}
id={data?.Investasi?.id as string}
status={"publish"} status={"publish"}
/> />
); );
@@ -64,10 +92,12 @@ export default function InvestmentDetailHolding() {
<StackCustom gap={"xs"}> <StackCustom gap={"xs"}>
<Grid> <Grid>
<Grid.Col span={6}> <Grid.Col span={6}>
<TextCustom bold>Nila Transaksi</TextCustom> <TextCustom bold>Nilai Transaksi</TextCustom>
</Grid.Col> </Grid.Col>
<Grid.Col span={6}> <Grid.Col span={6}>
<TextCustom bold>Rp. 7.500.000</TextCustom> <TextCustom bold>
Rp. {data ? formatCurrencyDisplay(data?.nominal) : ""}
</TextCustom>
</Grid.Col> </Grid.Col>
</Grid> </Grid>
<Grid> <Grid>
@@ -75,12 +105,16 @@ export default function InvestmentDetailHolding() {
<TextCustom bold>Saham Terbeli</TextCustom> <TextCustom bold>Saham Terbeli</TextCustom>
</Grid.Col> </Grid.Col>
<Grid.Col span={6}> <Grid.Col span={6}>
<TextCustom bold>300 Lembar</TextCustom> <TextCustom bold>
{data ? data?.lembarTerbeli : ""} Lembar
</TextCustom>
</Grid.Col> </Grid.Col>
</Grid> </Grid>
</StackCustom> </StackCustom>
</BaseBox> </BaseBox>
<Invesment_DetailDataPublishSection <Invesment_DetailDataPublishSection
data={data && data?.Investasi}
status={"publish"} status={"publish"}
bottomSection={bottomSection} bottomSection={bottomSection}
/> />

View File

@@ -1,9 +1,73 @@
import { BaseBox, Grid, Spacing, StackCustom, TextCustom, ViewWrapper } from "@/components"; /* eslint-disable react-hooks/exhaustive-deps */
import {
BaseBox,
Grid,
Spacing,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
import { apiInvestmentGetInvoice } from "@/service/api-client/api-investment";
import { GStyles } from "@/styles/global-styles"; import { GStyles } from "@/styles/global-styles";
import { dateTimeView } from "@/utils/dateTimeView";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import { FontAwesome6 } from "@expo/vector-icons"; import { FontAwesome6 } from "@expo/vector-icons";
import { useLocalSearchParams, useFocusEffect } from "expo-router";
import React from "react";
export default function InvestmentFailed() { export default function InvestmentFailed() {
const { id } = useLocalSearchParams();
console.log("[ID]", id);
const [data, setData] = React.useState<any | null>(null);
useFocusEffect(
React.useCallback(() => {
onLoadData();
}, [id])
);
const onLoadData = async () => {
try {
const response = await apiInvestmentGetInvoice({
id: id as string,
category: "invoice",
});
console.log("[RES INVOICE]", JSON.stringify(response.data, null, 2));
setData(response.data);
} catch (error) {
console.log("[ERROR]", error);
}
};
const listData = [
{
label: "Bank",
value: (data && data?.MasterBank?.namaBank) || "-",
},
{
label: "Rekening Penerima",
value: (data && data?.MasterBank?.namaAkun) || "-",
},
{
label: "No Rekening",
value: (data && data?.MasterBank?.norek) || "-",
},
{
label: "Jumlah",
value: `Rp ${data && formatCurrencyDisplay(data?.nominal)}` || "-",
},
{
label: "Tanggal",
value: (data && dateTimeView({ date: data?.createdAt })) || "-",
},
{
label: "Lembar Terbeli",
value: (data && formatCurrencyDisplay(data?.lembarTerbeli)) || "-",
},
];
return ( return (
<ViewWrapper> <ViewWrapper>
<StackCustom> <StackCustom>
@@ -11,8 +75,7 @@ export default function InvestmentFailed() {
<StackCustom> <StackCustom>
<TextCustom bold align="center"> <TextCustom bold align="center">
Transaksi anda gagal karena bukti transfer tidak sesuai dengan Transaksi anda gagal karena bukti transfer tidak sesuai dengan
data kami. Jika ini masalah khusus silahkan hubungi pada kontak data kami. Hubungi admin untuk memperbaiki masalah ini.
whatsapp kami.
</TextCustom> </TextCustom>
<FontAwesome6 <FontAwesome6
@@ -50,30 +113,3 @@ export default function InvestmentFailed() {
</ViewWrapper> </ViewWrapper>
); );
} }
const listData = [
{
label: "Bank",
value: " BCA",
},
{
label: "Rekening Penerima",
value: "Himpunan Pengusaha Muda Indonesia",
},
{
label: "No Rekening",
value: "2304235678854332",
},
{
label: "Jumlah",
value: "Rp. 1.000.000",
},
{
label: "Tanggal",
value: "2022-01-01",
},
{
label: "Lembar Terbeli",
value: "100",
},
];

View File

@@ -108,7 +108,9 @@ export default function InvestmentInvest() {
<TextCustom>Sisa Lembar Saham</TextCustom> <TextCustom>Sisa Lembar Saham</TextCustom>
</Grid.Col> </Grid.Col>
<Grid.Col span={6} style={{ alignItems: "flex-end" }}> <Grid.Col span={6} style={{ alignItems: "flex-end" }}>
<TextCustom>{data?.sisaLembar || "-"}</TextCustom> <TextCustom>
{data && formatCurrencyDisplay(data?.sisaLembar) || "-"}
</TextCustom>
</Grid.Col> </Grid.Col>
</Grid> </Grid>
<Grid> <Grid>
@@ -116,7 +118,9 @@ export default function InvestmentInvest() {
<TextCustom>Harga Per Lembar</TextCustom> <TextCustom>Harga Per Lembar</TextCustom>
</Grid.Col> </Grid.Col>
<Grid.Col span={6} style={{ alignItems: "flex-end" }}> <Grid.Col span={6} style={{ alignItems: "flex-end" }}>
<TextCustom>{data?.hargaLembar || "-"}</TextCustom> <TextCustom>
{data && formatCurrencyDisplay(data?.hargaLembar) || "-"}
</TextCustom>
</Grid.Col> </Grid.Col>
</Grid> </Grid>
<Grid> <Grid>

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
BaseBox, BaseBox,
Grid, Grid,
@@ -7,10 +8,66 @@ import {
ViewWrapper, ViewWrapper,
} from "@/components"; } from "@/components";
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
import { apiInvestmentGetInvoice } from "@/service/api-client/api-investment";
import { GStyles } from "@/styles/global-styles"; import { GStyles } from "@/styles/global-styles";
import { dateTimeView } from "@/utils/dateTimeView";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import { FontAwesome6 } from "@expo/vector-icons"; import { FontAwesome6 } from "@expo/vector-icons";
import { useFocusEffect, useLocalSearchParams } from "expo-router";
import React from "react";
export default function InvestmentSuccess() { export default function InvestmentSuccess() {
const { id } = useLocalSearchParams();
console.log("[ID]", id);
const [data, setData] = React.useState<any | null>(null);
useFocusEffect(
React.useCallback(() => {
onLoadData();
}, [id])
);
const onLoadData = async () => {
try {
const response = await apiInvestmentGetInvoice({
id: id as string,
category: "invoice",
});
console.log("[RES INVOICE]", JSON.stringify(response.data, null, 2));
setData(response.data);
} catch (error) {
console.log("[ERROR]", error);
}
};
const listData = [
{
label: "Bank",
value: (data && data?.MasterBank?.namaBank) || "-",
},
{
label: "Rekening Penerima",
value: (data && data?.MasterBank?.namaAkun) || "-",
},
{
label: "No Rekening",
value: (data && data?.MasterBank?.norek) || "-",
},
{
label: "Jumlah",
value: `Rp ${data && formatCurrencyDisplay(data?.nominal)}` || "-",
},
{
label: "Tanggal",
value: (data && dateTimeView({ date: data?.createdAt })) || "-",
},
{
label: "Lembar Terbeli",
value: (data && formatCurrencyDisplay(data?.lembarTerbeli)) || "-",
},
];
return ( return (
<ViewWrapper> <ViewWrapper>
<StackCustom> <StackCustom>
@@ -37,7 +94,6 @@ export default function InvestmentSuccess() {
<Spacing /> <Spacing />
<StackCustom> <StackCustom>
{listData.map((item, i) => ( {listData.map((item, i) => (
<Grid key={i}> <Grid key={i}>
@@ -45,7 +101,9 @@ export default function InvestmentSuccess() {
<TextCustom bold>{item.label}</TextCustom> <TextCustom bold>{item.label}</TextCustom>
</Grid.Col> </Grid.Col>
<Grid.Col span={7}> <Grid.Col span={7}>
<TextCustom style={{paddingLeft: 10}}>{item.value}</TextCustom> <TextCustom style={{ paddingLeft: 10 }}>
{item.value}
</TextCustom>
</Grid.Col> </Grid.Col>
</Grid> </Grid>
))} ))}
@@ -55,30 +113,3 @@ export default function InvestmentSuccess() {
</ViewWrapper> </ViewWrapper>
); );
} }
const listData = [
{
label: "Bank",
value: " BCA",
},
{
label: "Rekening Penerima",
value: "Himpunan Pengusaha Muda Indonesia",
},
{
label: "No Rekening",
value: "2304235678854332",
},
{
label: "Jumlah",
value: "Rp. 1.000.000",
},
{
label: "Tanggal",
value: "2022-01-01",
},
{
label: "Lembar Terbeli",
value: "100",
},
];

View File

@@ -1,20 +1,66 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
AvatarUsernameAndOtherComponent, AvatarUsernameAndOtherComponent,
BoxWithHeaderSection, BoxWithHeaderSection,
LoaderCustom,
TextCustom, TextCustom,
ViewWrapper, ViewWrapper,
} from "@/components"; } from "@/components";
import NoDataText from "@/components/_ShareComponent/NoDataText";
import { apiInvestmentGetInvestorById } from "@/service/api-client/api-investment";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import { useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash";
import { useCallback, useState } from "react";
export default function InvestmentInvestor() { export default function InvestmentInvestor() {
const { id } = useLocalSearchParams();
const [list, setList] = useState<any[] | null>(null);
const [loadingList, setLoadingList] = useState(false);
useFocusEffect(
useCallback(() => {
onLoadList();
}, [id])
);
const onLoadList = async () => {
try {
setLoadingList(true);
const response = await apiInvestmentGetInvestorById({
id: id as string,
})
console.log("[DATA LIST]", JSON.stringify(response.data, null, 2));
setList(response.data);
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadingList(false);
}
}
return ( return (
<> <>
<ViewWrapper> <ViewWrapper>
{Array.from({ length: 10 }).map((_, index) => ( {loadingList ? (
<LoaderCustom />
) : _.isEmpty(list) ? (
<NoDataText />
) : (
list?.map((item: any, index: number) => (
<BoxWithHeaderSection key={index}> <BoxWithHeaderSection key={index}>
<AvatarUsernameAndOtherComponent /> <AvatarUsernameAndOtherComponent
<TextCustom bold>Rp. 7.000.000</TextCustom> avatar={item?.Author?.Profile?.imageId}
name={item?.Author?.username}
avatarHref={`/profile/${item?.Author?.Profile?.id}`}
/>
<TextCustom bold>
Rp. {formatCurrencyDisplay(item?.nominal)}
</TextCustom>
</BoxWithHeaderSection> </BoxWithHeaderSection>
))} ))
)}
</ViewWrapper> </ViewWrapper>
</> </>
); );

View File

@@ -53,8 +53,6 @@ export default function AdminDonationDetail() {
id: id as string, id: id as string,
}); });
console.log("[RES GET BY ID]", JSON.stringify(response, null, 2));
if (response.success) { if (response.success) {
setData(response.data.donasi); setData(response.data.donasi);
setCountDonatur(response.data.donatur); setCountDonatur(response.data.donatur);
@@ -79,7 +77,9 @@ export default function AdminDonationDetail() {
value: value:
data && data?.DonasiMaster_Status?.name ? ( data && data?.DonasiMaster_Status?.name ? (
<BadgeCustom <BadgeCustom
color={colorBadgeStatus({ status: data?.DonasiMaster_Status?.name })} color={colorBadgeStatus({
status: data?.DonasiMaster_Status?.name,
})}
> >
{_.startCase(data?.DonasiMaster_Status?.name)} {_.startCase(data?.DonasiMaster_Status?.name)}
</BadgeCustom> </BadgeCustom>
@@ -107,7 +107,7 @@ export default function AdminDonationDetail() {
const listPencarianDana = [ const listPencarianDana = [
{ {
label: "Total Dana Dicairkan", label: "Total Dana Dicairkan",
value: `Rp ${(data && data?.totalPencairan) || 0}`, value: `Rp ${(data && formatCurrencyDisplay(data?.totalPencairan)) || 0}`,
}, },
{ {
label: "Sisa Dana Masuk", label: "Sisa Dana Masuk",
@@ -207,7 +207,15 @@ export default function AdminDonationDetail() {
iconLeft={ iconLeft={
<Ionicons name="cash-outline" size={ICON_SIZE_BUTTON} /> <Ionicons name="cash-outline" size={ICON_SIZE_BUTTON} />
} }
disabled={data?.terkumpul - data?.totalPencairan <= 0}
onPress={() => { onPress={() => {
if (data?.terkumpul - data?.totalPencairan <= 0) {
Toast.show({
type: "error",
text1: "Tidak ada dana yang tersisa",
});
return;
}
router.push(`/admin/donation/${id}/disbursement-of-funds`); router.push(`/admin/donation/${id}/disbursement-of-funds`);
}} }}
> >
@@ -227,7 +235,6 @@ export default function AdminDonationDetail() {
/> />
<Spacing /> <Spacing />
<StackCustom gap={"xs"}> <StackCustom gap={"xs"}>
<GridDetail_4_8 <GridDetail_4_8
label={<TextCustom bold>Jumlah Donatur</TextCustom>} label={<TextCustom bold>Jumlah Donatur</TextCustom>}

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
BaseBox, BaseBox,
ButtonCustom, ButtonCustom,
@@ -7,27 +8,53 @@ import {
} from "@/components"; } from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle"; import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8"; import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8";
import dayjs from "dayjs"; import { apiAdminDonationDisbursementOfFundsListById } from "@/service/api-admin/api-admin-donation";
import { router, useLocalSearchParams } from "expo-router"; import { dateTimeView } from "@/utils/dateTimeView";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import React, { useCallback } from "react";
export default function AdminDonationDetailDisbursementOfFunds() { export default function AdminDonationDetailDisbursementOfFunds() {
const { id } = useLocalSearchParams(); const { id } = useLocalSearchParams();
const [data, setData] = React.useState<any | null>(null);
useFocusEffect(
useCallback(() => {
onLoadData();
}, [id])
);
const onLoadData = async () => {
try {
const response = await apiAdminDonationDisbursementOfFundsListById({
id: id as string,
category: "get-one",
});
if (response.success) {
setData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
}
};
const listData = [ const listData = [
{ {
label: "Nominal", label: "Nominal",
value: "Rp 1.000.000", value: `Rp ${(data && formatCurrencyDisplay(data?.nominalCair)) || 0}`,
}, },
{ {
label: "Tanggal", label: "Tanggal",
value: dayjs().format("DD-MM-YYYY HH:mm"), value: dateTimeView({ date: data?.createdAt }),
}, },
{ {
label: "Judul", label: "Judul",
value: `Judul Pencairan Dana ${id}`, value: (data && data?.title) || "-",
}, },
{ {
label: "Deskripsi", label: "Deskripsi",
value: `Lorem ipsum dolor sit amet consectetur adipisicing elit. Itaque velit eos facere a dicta nemo repellendus harum laboriosam quos, earum reprehenderit. Nisi sapiente, quo earum quis alias ullam temporibus quidem.`, value: (data && data?.deskripsi) || "-",
}, },
]; ];
return ( return (
@@ -39,7 +66,7 @@ export default function AdminDonationDetailDisbursementOfFunds() {
> >
<BaseBox> <BaseBox>
<StackCustom> <StackCustom>
{listData.map((item, index) => ( {listData?.map((item, index) => (
<GridDetail_4_8 <GridDetail_4_8
key={index} key={index}
label={<TextCustom bold>{item.label}</TextCustom>} label={<TextCustom bold>{item.label}</TextCustom>}
@@ -51,7 +78,7 @@ export default function AdminDonationDetailDisbursementOfFunds() {
<ButtonCustom <ButtonCustom
onPress={() => onPress={() =>
router.push(`/(application)/(image)/preview-image/${id}`) router.push(`/(application)/(image)/preview-image/${data?.imageId}`)
} }
> >
Cek Bukti Transaksi Cek Bukti Transaksi

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
BaseBox, BaseBox,
BoxButtonOnFooter, BoxButtonOnFooter,
@@ -12,15 +13,122 @@ import {
ViewWrapper, ViewWrapper,
} from "@/components"; } from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle"; import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { router, useLocalSearchParams } from "expo-router"; import DIRECTORY_ID from "@/constants/directory-id";
import { apiAdminDonationDetailById, apiAdminDonationDisbursementOfFundsCreated } from "@/service/api-admin/api-admin-donation";
import { uploadFileService } from "@/service/upload-service";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import pickFile from "@/utils/pickFile";
import { Image } from "expo-image";
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import React from "react";
import Toast from "react-native-toast-message";
export default function AdminDonationDisbursementOfFunds() { export default function AdminDonationDisbursementOfFunds() {
const { id } = useLocalSearchParams(); const { id } = useLocalSearchParams();
const handleSubmit = (
const [data, setData] = React.useState<any | null>(null);
const [isLoading, setIsLoading] = React.useState(false);
const [value, setValue] = React.useState({
nominalCair: "",
title: "",
deskripsi: "",
});
const [image, setImage] = React.useState<any | null>(null);
useFocusEffect(
React.useCallback(() => {
onLoadData();
}, [id])
);
const onLoadData = async () => {
try {
const response = await apiAdminDonationDetailById({
id: id as string,
});
if (response.success) {
setData(response.data.donasi);
}
} catch (error) {
console.log("[ERROR]", error);
setData(null);
}
};
const handleSubmit = async () => {
if (!image) {
Toast.show({
type: "error",
text1: "Harap upload bukti transfer",
});
return;
}
if (!value.nominalCair || !value.title || !value.deskripsi) {
Toast.show({
type: "error",
text1: "Harap isi semua data",
});
return;
}
try {
setIsLoading(true);
const uploadImage = await uploadFileService({
dirId: DIRECTORY_ID.donasi_bukti_trf_pencairan_dana,
imageUri: image.uri,
});
if (!uploadFileService) {
Toast.show({
type: "error",
text1: "Gagal mengunggah gambar",
});
return;
}
const imageId = uploadImage.data.id;
const newData = {
...value,
imageId: imageId,
};
const response = await apiAdminDonationDisbursementOfFundsCreated({
id: id as string,
data: newData,
});
if (!response.success) {
Toast.show({
type: "error",
text1: response.message,
});
return;
}
Toast.show({
type: "success",
text1: "Pencairan dana berhasil disimpan",
});
router.back();
} catch (error) {
console.log("[ERROR]", error);
} finally {
setIsLoading(false);
}
};
const buttonSubmit = (
<BoxButtonOnFooter> <BoxButtonOnFooter>
<ButtonCustom <ButtonCustom
isLoading={isLoading}
onPress={() => { onPress={() => {
router.back(); handleSubmit();
}} }}
> >
Simpan Simpan
@@ -31,7 +139,7 @@ export default function AdminDonationDisbursementOfFunds() {
return ( return (
<ViewWrapper <ViewWrapper
headerComponent={<AdminBackButtonAntTitle title="Pencairan Dana" />} headerComponent={<AdminBackButtonAntTitle title="Pencairan Dana" />}
footerComponent={handleSubmit} footerComponent={buttonSubmit}
> >
<BaseBox> <BaseBox>
<StackCustom gap="md"> <StackCustom gap="md">
@@ -39,7 +147,7 @@ export default function AdminDonationDisbursementOfFunds() {
Dana Tersisa Dana Tersisa
</TextCustom> </TextCustom>
<TextCustom align="center" bold size="large"> <TextCustom align="center" bold size="large">
Rp 1.000.000 Rp {formatCurrencyDisplay(data?.terkumpul - data?.totalPencairan)}
</TextCustom> </TextCustom>
</StackCustom> </StackCustom>
</BaseBox> </BaseBox>
@@ -56,9 +164,27 @@ export default function AdminDonationDisbursementOfFunds() {
label="Nominal" label="Nominal"
placeholder="0" placeholder="0"
iconLeft={"Rp"} iconLeft={"Rp"}
value={value.nominalCair}
onChangeText={(text) => {
setValue({
...value,
nominalCair: text,
});
}}
/> />
<TextInputCustom required label="Judul" placeholder="Masukan judul" /> <TextInputCustom
required
label="Judul"
placeholder="Masukan judul"
value={value.title}
onChangeText={(text) => {
setValue({
...value,
title: text,
});
}}
/>
<TextAreaCustom <TextAreaCustom
required required
@@ -66,20 +192,37 @@ export default function AdminDonationDisbursementOfFunds() {
placeholder="Masukan deskripsi" placeholder="Masukan deskripsi"
showCount showCount
maxLength={500} maxLength={500}
value={value.deskripsi}
onChangeText={(text) => {
setValue({
...value,
deskripsi: text,
});
}}
/> />
</StackCustom> </StackCustom>
</BaseBox> </BaseBox>
<InformationBox text="Wajib menyertakan bukti transfer" />
<Spacing />
<InformationBox text="Wajib menyertakan bukti transfer" />
<ButtonCenteredOnly <ButtonCenteredOnly
onPress={() => { onPress={() => {
router.push(`/(application)/(image)/take-picture/${id}`); pickFile({
allowedType: "image",
aspectRatio: [9, 16],
setImageUri: (file) => {
setImage(file);
},
});
}} }}
icon="upload" icon="upload"
> >
Upload Upload
</ButtonCenteredOnly> </ButtonCenteredOnly>
<Spacing /> <Spacing />
<Image source={image?.uri} style={{ width: "100%", height: 300 }} />
<Spacing />
</ViewWrapper> </ViewWrapper>
); );
} }

View File

@@ -1,21 +1,54 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
ActionIcon, ActionIcon,
CenterCustom, CenterCustom,
Divider, Divider,
LoaderCustom,
StackCustom, StackCustom,
TextCustom, TextCustom,
ViewWrapper ViewWrapper,
} from "@/components"; } from "@/components";
import { IconView } from "@/components/_Icon/IconComponent"; import { IconView } from "@/components/_Icon/IconComponent";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle"; import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { GridViewCustomSpan } from "@/components/_ShareComponent/GridViewCustomSpan"; import { GridViewCustomSpan } from "@/components/_ShareComponent/GridViewCustomSpan";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value"; import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { apiAdminDonationDisbursementOfFundsListById } from "@/service/api-admin/api-admin-donation";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import dayjs from "dayjs"; import dayjs from "dayjs";
import { router, useLocalSearchParams } from "expo-router"; import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash";
import React, { useCallback } from "react";
import { View } from "react-native"; import { View } from "react-native";
export default function AdminDonasiListOfDisbursementOfFunds() { export default function AdminDonasiListOfDisbursementOfFunds() {
const { id } = useLocalSearchParams(); const { id } = useLocalSearchParams();
const [listData, setListData] = React.useState<any[] | null>(null);
const [loadData, setLoadData] = React.useState(false);
useFocusEffect(
useCallback(() => {
onLoadData();
}, [id])
);
const onLoadData = async () => {
try {
setLoadData(true);
const response = await apiAdminDonationDisbursementOfFundsListById({
id: id as string,
category: "get-all",
});
if (response.success) {
setListData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadData(false);
}
};
return ( return (
<> <>
<ViewWrapper <ViewWrapper
@@ -45,7 +78,14 @@ export default function AdminDonasiListOfDisbursementOfFunds() {
/> />
<Divider /> <Divider />
<StackCustom> <StackCustom>
{Array.from({ length: 10 }).map((_, index) => ( {loadData ? (
<LoaderCustom />
) : _.isEmpty(listData) ? (
<TextCustom align="center" color="gray">
Belum ada data
</TextCustom>
) : (
listData?.map((item, index) => (
<View key={index}> <View key={index}>
<GridViewCustomSpan <GridViewCustomSpan
span1={3} span1={3}
@@ -54,27 +94,31 @@ export default function AdminDonasiListOfDisbursementOfFunds() {
component1={ component1={
<CenterCustom> <CenterCustom>
<ActionIcon <ActionIcon
icon={<IconView size={ICON_SIZE_BUTTON} color="black" />} icon={
<IconView size={ICON_SIZE_BUTTON} color="black" />
}
onPress={() => { onPress={() => {
router.push( router.push(
`/admin/donation/${id}/detail-disbursement-of-funds` `/admin/donation/${item?.id}/detail-disbursement-of-funds`
); );
}} }}
/> />
</CenterCustom> </CenterCustom>
} }
component2={ component2={
<TextCustom bold align="center" truncate> <TextCustom align="center" truncate>
{dayjs() {dayjs(item?.createdAt).format("DD-MM-YYYY")}
.add(index + 1, "day") </TextCustom>
.format("DD-MM-YYYY HH:mm")} }
component3={
<TextCustom align="center" truncate>
Rp. {formatCurrencyDisplay(item?.nominalCair)}
</TextCustom> </TextCustom>
} }
component3={<TextCustom>Rp. 1.000.000</TextCustom>}
/> />
<Divider />
</View> </View>
))} ))
)}
</StackCustom> </StackCustom>
</ViewWrapper> </ViewWrapper>
</> </>

View File

@@ -38,7 +38,7 @@ export default function AdminEventDetail() {
const [data, setData] = React.useState<any | null>(null); const [data, setData] = React.useState<any | null>(null);
const [loadData, setLoadData] = React.useState(false); const [loadData, setLoadData] = React.useState(false);
const deepLinkURL = `${DEEP_LINK_URL}/--/event/${id}/confirmation?userId=${user?.id}`; const deepLinkURL = `${DEEP_LINK_URL}/event/${id}/confirmation?userId=${user?.id}`;
useFocusEffect( useFocusEffect(
useCallback(() => { useCallback(() => {
onLoadData(); onLoadData();
@@ -190,6 +190,8 @@ export default function AdminEventDetail() {
// color="black" // color="black"
/> />
)} )}
<TextCustom align="center">{deepLinkURL}</TextCustom>
</StackCustom> </StackCustom>
</BaseBox> </BaseBox>
)} )}

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
ActionIcon, ActionIcon,
AlertDefaultSystem, AlertDefaultSystem,
@@ -11,7 +12,7 @@ import {
Spacing, Spacing,
StackCustom, StackCustom,
TextCustom, TextCustom,
ViewWrapper ViewWrapper,
} from "@/components"; } from "@/components";
import { IconProspectus } from "@/components/_Icon"; import { IconProspectus } from "@/components/_Icon";
import { IconDot, IconList } from "@/components/_Icon/IconComponent"; import { IconDot, IconList } from "@/components/_Icon/IconComponent";
@@ -19,75 +20,141 @@ 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 { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8"; import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8";
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";
import { router, useLocalSearchParams } from "expo-router"; import {
apiAdminInvestasiUpdateByStatus,
apiAdminInvestmentDetailById,
} from "@/service/api-admin/api-admin-investment";
import { colorBadgeStatus } from "@/utils/colorBadge";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash"; import _ from "lodash";
import React from "react"; import React from "react";
import Toast from "react-native-toast-message";
export default function AdminInvestmentDetail() { export default function AdminInvestmentDetail() {
const { id, status } = useLocalSearchParams(); const { id, status } = useLocalSearchParams();
const [openDrawer, setOpenDrawer] = React.useState(false); const [openDrawer, setOpenDrawer] = React.useState(false);
const colorBadge = () => { const [data, setData] = React.useState<any | null>(null);
if (status === "publish") { const [isLoading, setLoading] = React.useState(false);
return MainColor.green;
} else if (status === "review") { useFocusEffect(
return MainColor.orange; React.useCallback(() => {
} else if (status === "reject") { onLoadData();
return MainColor.red; }, [id])
} else { );
return MainColor.placeholder;
const onLoadData = async () => {
try {
const response = await apiAdminInvestmentDetailById({ id: id as string });
// console.log("[GETONE INVEST]", JSON.stringify(response, null, 2));
if (response.success) {
setData(response.data);
}
} catch (error) {
console.log(error);
} }
}; };
const listData = [ const listData = [
{ {
label: "Username", label: "Username",
value: `Bagas Banuna ${id}`, value: (data && data?.author?.username) || "-",
}, },
{ {
label: "Judul", label: "Judul",
value: `Donasi Lorem ipsum dolor sit amet, consectetur adipisicing elit.`, value: (data && data?.title) || "-",
}, },
{ {
label: "Status", label: "Status",
value: ( value:
<BadgeCustom color={colorBadge()}> data && data?.MasterStatusInvestasi?.name ? (
{_.startCase(status as string)} <BadgeCustom
color={colorBadgeStatus({
status: data?.MasterStatusInvestasi?.name as string,
})}
>
{_.startCase(data?.MasterStatusInvestasi?.name as string)}
</BadgeCustom> </BadgeCustom>
) : (
"-"
), ),
}, },
{ {
label: "Dana Dibutuhkan", label: "Dana Dibutuhkan",
value: "Rp 10.000.000", value: `Rp. ${
(data && data?.targetDana && formatCurrencyDisplay(data?.targetDana)) ||
"-"
}`,
}, },
{ {
label: "Harga Perlembar", label: "Harga Perlembar",
value: "Rp 2500", value: `Rp. ${
(data &&
data?.hargaLembar &&
formatCurrencyDisplay(data?.hargaLembar)) ||
"-"
}`,
}, },
{ {
label: "Total Lembar", label: "Total Lembar",
value: "2490 lembar", value:
(data &&
data?.totalLembar &&
formatCurrencyDisplay(data?.totalLembar)) ||
"-",
}, },
{ {
label: "ROI", label: "ROI",
value: "4 %", value: `${(data && data?.roi && data?.roi) || 0} %`,
}, },
{ {
label: "Pembagian Deviden", label: "Pembagian Deviden",
value: "3 bulan", value: (data && data?.MasterPembagianDeviden?.name) + " bulan" || "-",
}, },
{ {
label: "Jadwal Pembagian", label: "Jadwal Pembagian",
value: "Selamanya", value: (data && data?.MasterPeriodeDeviden?.name) || "-",
}, },
{ {
label: "Pencarian Investor", label: "Pencarian Investor",
value: "30 Hari", value: (data && data?.MasterPencarianInvestor?.name) + " hari" || "-",
}, },
]; ];
const handlerSubmitPublish = async () => {
try {
setLoading(true);
const response = await apiAdminInvestasiUpdateByStatus({
id: id as string,
status: "publish",
data: data,
});
// console.log("[GET ON INVEST]", JSON.stringify(response, null, 2));
if (!response.success) {
Toast.show({
type: "error",
text1: "Gagal mempublikasikan data",
});
return;
}
Toast.show({
type: "success",
text1: "Berhasil mempublikasikan data",
});
router.replace(`/admin/investment/publish/status`);
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoading(false);
}
};
const rightComponent = ( const rightComponent = (
<ActionIcon <ActionIcon
icon={<IconDot size={ICON_SIZE_BUTTON} />} icon={<IconDot size={ICON_SIZE_BUTTON} />}
@@ -109,16 +176,28 @@ export default function AdminInvestmentDetail() {
> >
{status === "publish" && ( {status === "publish" && (
<BaseBox> <BaseBox>
<ProgressCustom size="lg" /> <ProgressCustom
label={data && `${data.progress}%` || "0%"}
value={data && data.progress || 0}
size="lg"
/>
<Spacing /> <Spacing />
<StackCustom gap={"xs"}> <StackCustom gap={"xs"}>
<GridDetail_4_8 <GridDetail_4_8
label={<TextCustom bold>Sisa Saham</TextCustom>} label={<TextCustom bold>Sisa Saham</TextCustom>}
value={<TextCustom>2490 lembar</TextCustom>} value={
<TextCustom>
{data && formatCurrencyDisplay(data && data?.sisaLembar)} lembar
</TextCustom>
}
/> />
<GridDetail_4_8 <GridDetail_4_8
label={<TextCustom bold>Validasi Transaksi</TextCustom>} label={<TextCustom bold>Validasi Transaksi</TextCustom>}
value={<TextCustom>4 Transaksi</TextCustom>} value={
<TextCustom>
{data && data?.Investasi_Invoice.length} Proses
</TextCustom>
}
/> />
</StackCustom> </StackCustom>
</BaseBox> </BaseBox>
@@ -126,7 +205,7 @@ export default function AdminInvestmentDetail() {
<BaseBox> <BaseBox>
<StackCustom> <StackCustom>
<DummyLandscapeImage /> <DummyLandscapeImage imageId={data?.imageId} />
{listData.map((item, i) => ( {listData.map((item, i) => (
<GridDetail_4_8 <GridDetail_4_8
key={i} key={i}
@@ -150,7 +229,9 @@ export default function AdminInvestmentDetail() {
/> />
} }
onPress={() => { onPress={() => {
router.push(`/(application)/(file)/${id}`); router.push(
`/(application)/(file)/${data?.prospektusFileId}`
);
}} }}
> >
Preview Preview
@@ -161,9 +242,15 @@ export default function AdminInvestmentDetail() {
label={<TextCustom bold>File Dokumen</TextCustom>} label={<TextCustom bold>File Dokumen</TextCustom>}
value={ value={
<StackCustom> <StackCustom>
{Array.from({ length: 5 }).map((_, i) => ( {_.isEmpty(data?.DokumenInvestasi) ? (
<TextCustom align="center">-</TextCustom>
) : (
data?.DokumenInvestasi?.map((item: any, index: number) => {
const titleFix = item?.title?.substring(0, 10) || "";
return (
<ButtonCustom <ButtonCustom
key={i} key={item.id || index} // ✅ pastikan key unik
iconLeft={ iconLeft={
<IconProspectus <IconProspectus
size={ICON_SIZE_BUTTON} size={ICON_SIZE_BUTTON}
@@ -171,36 +258,50 @@ export default function AdminInvestmentDetail() {
/> />
} }
onPress={() => { onPress={() => {
router.push(`/(application)/(file)/${id}`); router.push(
`/(application)/(file)/${item?.fileId}`
);
}} }}
> >
Dokumen {i + 1} <TextCustom color="black" truncate>
{titleFix}...
</TextCustom>
</ButtonCustom> </ButtonCustom>
))} );
})
)}
</StackCustom> </StackCustom>
} }
/> />
</StackCustom> </StackCustom>
</BaseBox> </BaseBox>
{data &&
data?.catatan &&
(status === "review" || status === "reject") && (
<ReportBox text={data?.catatan} />
)}
{status === "review" && ( {status === "review" && (
<AdminButtonReview <AdminButtonReview
isLoading={isLoading}
onPublish={() => { onPublish={() => {
AlertDefaultSystem({ AlertDefaultSystem({
title: "Publish", title: "Publish",
message: "Apakah anda yakin ingin mempublikasikan data ini?", message: "Apakah anda yakin ingin mempublikasikan data ini?",
textLeft: "Batal", textLeft: "Batal",
textRight: "Ya", textRight: "Ya",
onPressLeft: () => {
router.back();
},
onPressRight: () => { onPressRight: () => {
router.back(); handlerSubmitPublish();
}, },
}); });
}} }}
onReject={() => { onReject={() => {
router.push(`/admin/investment/${id}/reject-input`); router.push(
`/admin/investment/${id}/reject-input?status=${_.lowerCase(
data?.MasterStatusInvestasi?.name
)}`
);
}} }}
/> />
)} )}

View File

@@ -1,67 +1,226 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
AlertDefaultSystem,
BadgeCustom, BadgeCustom,
BaseBox, BaseBox,
BoxButtonOnFooter,
ButtonCustom, ButtonCustom,
Spacing,
StackCustom, StackCustom,
TextCustom, TextCustom,
ViewWrapper, ViewWrapper,
} from "@/components"; } from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle"; import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8"; import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8";
import GridTwoView from "@/components/_ShareComponent/GridTwoView";
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
import dayjs from "dayjs"; import {
import { router, useLocalSearchParams } from "expo-router"; apiAdminInvestmentGetOneInvoiceById,
apiAdminInvestmentUpdateInvoice,
} from "@/service/api-admin/api-admin-investment";
import { colorBadgeTransaction } from "@/utils/colorBadge";
import { dateTimeView } from "@/utils/dateTimeView";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import { useCallback, useState } from "react";
import Toast from "react-native-toast-message";
export default function AdminInvestmentTransactionDetail() { export default function AdminInvestmentTransactionDetail() {
const { id } = useLocalSearchParams(); const { id } = useLocalSearchParams();
const [data, setData] = useState<any | null>(null);
const [isLoading, setLoading] = useState<boolean>(false);
const buttonAction = ( useFocusEffect(
<BoxButtonOnFooter> useCallback(() => {
<ButtonCustom onPress={() => router.back()}>Terima</ButtonCustom> onLoadData();
</BoxButtonOnFooter> }, [id])
); );
const onLoadData = async () => {
try {
const response = await apiAdminInvestmentGetOneInvoiceById({
id: id as string,
});
// console.log("[RESPONSE]", JSON.stringify(response, null, 2));
if (response.success) {
setData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
}
};
const listData = [ const listData = [
{ {
label: "Investor", label: "Investor",
value: "Bagas Banuna", value: (data && data?.Author?.username) || "-",
}, },
{ {
label: "Bank", label: "Bank",
value: "BCA", value: (data && data?.MasterBank?.namaBank) || "-",
}, },
{ {
label: "Jumlah Investasi", label: "Jumlah Investasi",
value: "Rp. 1.000.000", value: (data && `Rp. ${formatCurrencyDisplay(data?.nominal)}`) || "-",
},
{
label: "Lembar terbeli",
value: (data && formatCurrencyDisplay(data?.lembarTerbeli)) || "-",
}, },
{ {
label: "Status", label: "Status",
value: <BadgeCustom color={MainColor.green}>Berhasil</BadgeCustom>, value:
data && data?.StatusInvoice?.name ? (
<BadgeCustom
color={colorBadgeTransaction({
status: data?.StatusInvoice?.name,
})}
>
{data?.StatusInvoice?.name}
</BadgeCustom>
) : (
"-"
),
}, },
{ {
label: "Tanggal", label: "Tanggal",
value: dayjs().format("DD-MM-YYYY HH:mm:ss"), value: (data && dateTimeView({ date: data?.createdAt })) || "-",
}, },
{ {
label: "Bukti Transfer", label: "Bukti Transfer",
value: ( value:
data && data?.imageId ? (
<ButtonCustom <ButtonCustom
onPress={() => onPress={() =>
router.push(`/(application)/(image)/preview-image/${id}`) router.push(
`/(application)/(image)/preview-image/${data?.imageId}`
)
} }
> >
Cek Cek
</ButtonCustom> </ButtonCustom>
) : (
"-"
), ),
}, },
]; ];
const handlerSubmit = async ({
category,
}: {
category: "accept" | "deny";
}) => {
try {
setLoading(true);
const response = await apiAdminInvestmentUpdateInvoice({
id: id as string,
category: category,
data: {
investasiId: data?.investasiId,
lembarTerbeli: data?.lembarTerbeli,
},
});
// console.log("[RESPONSE SUBMIT]", JSON.stringify(response, null, 2));
if (!response.success) {
Toast.show({
type: "error",
text1: "Gagal update status transaksi",
});
return;
}
Toast.show({
type: "success",
text1: "Berhasil update status transaksi",
});
router.back();
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoading(false);
}
};
const buttonAction = () => {
if (data?.StatusInvoice?.name === "Proses") {
return (
<GridTwoView
spanLeft={6}
spanRight={6}
styleLeft={{ paddingRight: 10 }}
styleRight={{ paddingLeft: 10 }}
leftIcon={
<ButtonCustom
isLoading={isLoading}
backgroundColor={MainColor.red}
textColor="white"
onPress={() => {
AlertDefaultSystem({
title: "Konfirmasi transaksi",
message: "Apakah anda yakin ingin menolak transaksi ini?",
textLeft: "Tidak",
textRight: "Ya",
onPressRight: () => {
handlerSubmit({
category: "deny",
});
},
});
}}
>
Tolak
</ButtonCustom>
}
rightIcon={
<ButtonCustom
isLoading={isLoading}
onPress={() => {
AlertDefaultSystem({
title: "Konfirmasi transaksi",
message: "Apakah anda yakin ingin menyetujui transaksi ini?",
textLeft: "Tidak",
textRight: "Ya",
onPressRight: () => {
handlerSubmit({
category: "accept",
});
},
});
}}
>
Terima
</ButtonCustom>
}
/>
);
} else if (data?.StatusInvoice?.name === "Gagal") {
return (
<>
<ButtonCustom textColor="red" onPress={() => router.back()}>
Gagal
</ButtonCustom>
</>
);
} else {
return (
<>
<ButtonCustom disabled={true}>
Status: {data?.StatusInvoice?.name}
</ButtonCustom>
</>
);
}
};
return ( return (
<> <>
<ViewWrapper <ViewWrapper
headerComponent={<AdminBackButtonAntTitle title="Detail Transaksi Investor" />} headerComponent={
footerComponent={buttonAction} <AdminBackButtonAntTitle title="Detail Transaksi Investor" />
}
// footerComponent={buttonAction()}
> >
<BaseBox> <BaseBox>
<StackCustom> <StackCustom>
@@ -74,6 +233,8 @@ export default function AdminInvestmentTransactionDetail() {
))} ))}
</StackCustom> </StackCustom>
</BaseBox> </BaseBox>
<Spacing />
{buttonAction()}
</ViewWrapper> </ViewWrapper>
</> </>
); );

View File

@@ -1,7 +1,9 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
ActionIcon, ActionIcon,
BadgeCustom, BadgeCustom,
CenterCustom, CenterCustom,
LoaderCustom,
SelectCustom, SelectCustom,
StackCustom, StackCustom,
TextCustom, TextCustom,
@@ -10,23 +12,98 @@ import {
import { IconView } from "@/components/_Icon/IconComponent"; import { IconView } from "@/components/_Icon/IconComponent";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle"; import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { GridViewCustomSpan } from "@/components/_ShareComponent/GridViewCustomSpan"; import { GridViewCustomSpan } from "@/components/_ShareComponent/GridViewCustomSpan";
import { MainColor } from "@/constants/color-palet"; import NoDataText from "@/components/_ShareComponent/NoDataText";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value"; import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { dummyMasterStatusTransaction } from "@/lib/dummy-data/_master/status-transaction"; import { apiAdminInvestmentListOfInvestor } from "@/service/api-admin/api-admin-investment";
import { router, useLocalSearchParams } from "expo-router"; import { apiMasterTransaction } from "@/service/api-client/api-master";
import React from "react"; import { colorBadgeTransaction } from "@/utils/colorBadge";
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash";
import React, { useEffect } from "react";
import { View } from "react-native"; import { View } from "react-native";
import { Divider } from "react-native-paper"; import { Divider } from "react-native-paper";
export default function AdminInvestmentListOfInvestor() { export default function AdminInvestmentListOfInvestor() {
const { id } = useLocalSearchParams(); const { id } = useLocalSearchParams();
console.log("[ID]", id);
const [listData, setListData] = React.useState<any[] | null>(null);
const [loadData, setLoadData] = React.useState(false);
const [master, setMaster] = React.useState<any[]>([]);
const [selectValue, setSelectValue] = React.useState<string | null>(null);
const [selectedStatus, setSelectedStatus] = React.useState<string | null>(
null
);
useEffect(() => {
onLoadMaster();
}, []);
const onLoadMaster = async () => {
try {
const response = await apiMasterTransaction();
if (response.success) {
setMaster(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
setMaster([]);
}
};
useFocusEffect(
React.useCallback(() => {
onLoadData();
}, [id, selectValue])
);
const onLoadData = async () => {
try {
setLoadData(true);
const response = await apiAdminInvestmentListOfInvestor({
id: id as string,
status: selectedStatus as any,
});
console.log("[LIST OF INVESTOR]", JSON.stringify(response, null, 2));
if (response.success) {
setListData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
setListData([]);
} finally {
setLoadData(false);
}
};
useEffect(() => {
onLoadMaster();
}, []);
const searchComponent = ( const searchComponent = (
<View style={{ flexDirection: "row", gap: 5 }}> <View style={{ flexDirection: "row", gap: 5 }}>
<SelectCustom <SelectCustom
placeholder="Pilih status transaksi" placeholder="Pilih status transaksi"
data={dummyMasterStatusTransaction} data={
onChange={(value) => console.log(value)} _.isEmpty(master)
? []
: master?.map((item: any) => ({
label: item.name,
value: item.id,
}))
}
value={selectValue}
onChange={(value: any) => {
setSelectValue(value);
const nameSelected = master.find((item: any) => item.id === value);
const statusChooses = _.lowerCase(nameSelected?.name);
setSelectedStatus(statusChooses);
}}
styleContainer={{ width: "100%", marginBottom: 0 }} styleContainer={{ width: "100%", marginBottom: 0 }}
allowClear
/> />
</View> </View>
); );
@@ -40,9 +117,8 @@ export default function AdminInvestmentListOfInvestor() {
return ( return (
<> <>
<ViewWrapper <ViewWrapper headerComponent={headerComponent}>
headerComponent={headerComponent} <StackCustom>
>
<GridViewCustomSpan <GridViewCustomSpan
span1={3} span1={3}
span2={5} span2={5}
@@ -65,7 +141,12 @@ export default function AdminInvestmentListOfInvestor() {
/> />
<Divider /> <Divider />
<StackCustom> <StackCustom>
{Array.from({ length: 10 }).map((_, index) => ( {loadData ? (
<LoaderCustom />
) : _.isEmpty(listData) ? (
<NoDataText />
) : (
listData?.map((item: any, index: number) => (
<View key={index}> <View key={index}>
<GridViewCustomSpan <GridViewCustomSpan
span1={3} span1={3}
@@ -74,10 +155,14 @@ export default function AdminInvestmentListOfInvestor() {
component1={ component1={
<CenterCustom> <CenterCustom>
<ActionIcon <ActionIcon
icon={<IconView size={ICON_SIZE_BUTTON} color="black" />} icon={
<IconView size={ICON_SIZE_BUTTON} color="black" />
}
onPress={() => { onPress={() => {
router.push( router.push(
`/admin/investment/${id}/berhasil/transaction-detail` `/admin/investment/${item?.id}/${_.lowerCase(
item?.StatusInvoice?.name
)}/transaction-detail`
); );
}} }}
/> />
@@ -85,21 +170,24 @@ export default function AdminInvestmentListOfInvestor() {
} }
component2={ component2={
<TextCustom bold align="center" truncate> <TextCustom bold align="center" truncate>
Bagas Banuna {item?.Author?.username || "-"}
</TextCustom> </TextCustom>
} }
component3={ component3={
<BadgeCustom <BadgeCustom
style={{ alignSelf: "center" }} style={{ alignSelf: "center" }}
color={MainColor.green} color={colorBadgeTransaction({
status: item?.StatusInvoice?.name,
})}
> >
Berhasil {item?.StatusInvoice?.name}
</BadgeCustom> </BadgeCustom>
} }
/> />
<Divider />
</View> </View>
))} ))
)}
</StackCustom>
</StackCustom> </StackCustom>
</ViewWrapper> </ViewWrapper>
</> </>

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
AlertDefaultSystem, AlertDefaultSystem,
BoxButtonOnFooter, BoxButtonOnFooter,
@@ -6,15 +7,83 @@ 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 { router, useLocalSearchParams } from "expo-router"; import { apiAdminInvestasiUpdateByStatus, apiAdminInvestmentDetailById } from "@/service/api-admin/api-admin-investment";
import { useState } from "react"; import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import { useCallback, useState } from "react";
import Toast from "react-native-toast-message";
export default function AdminInvestmentRejectInput() { export default function AdminInvestmentRejectInput() {
const { id } = useLocalSearchParams(); const { id, status } = useLocalSearchParams();
const [value, setValue] = useState(id as string); console.log("[STATUS]", status);
const [value, setValue] = useState<any | null>(null);
const [isLoading , setLoading] = useState(false)
useFocusEffect(
useCallback(() => {
onLoadData();
}, [id])
);
const onLoadData = async () => {
try {
const response = await apiAdminInvestmentDetailById({ id: id as string });
console.log("[DATA]", JSON.stringify(response, null, 2));
if (response.success) {
setValue(response.data?.catatan);
}
} catch (error) {
console.log(error);
}
};
const handlerSubmit = async () => {
if (!value) {
Toast.show({
type: "error",
text1: "Harap masukan alasan penolakan",
});
return;
}
try {
setLoading(true)
const response = await apiAdminInvestasiUpdateByStatus({
id: id as string,
status: "reject",
data: value,
});
console.log("[RESPONSE]", JSON.stringify(response, null, 2));
if (!response.success) {
Toast.show({
type: "error",
text1: "Gagal melakukan report",
});
return;
}
Toast.show({
type: "success",
text1: "Berhasil melakukan report",
});
if (status === "review") {
router.replace(`/admin/investment/reject/status`);
} else {
router.back();
}
} catch (error) {
console.error(["ERROR"], error);
} finally {
setLoading(false)
}
};
const buttonSubmit = ( const buttonSubmit = (
<BoxButtonOnFooter> <BoxButtonOnFooter>
<AdminButtonReject <AdminButtonReject
isLoading={isLoading}
title="Reject" title="Reject"
onReject={() => onReject={() =>
AlertDefaultSystem({ AlertDefaultSystem({
@@ -22,12 +91,8 @@ export default function AdminInvestmentRejectInput() {
message: "Apakah anda yakin ingin menolak data ini?", message: "Apakah anda yakin ingin menolak data ini?",
textLeft: "Batal", textLeft: "Batal",
textRight: "Ya", textRight: "Ya",
onPressLeft: () => {
router.back();
},
onPressRight: () => { onPressRight: () => {
console.log("value:", value); handlerSubmit();
router.replace(`/admin/investment/reject/status`);
}, },
}) })
} }
@@ -39,7 +104,9 @@ export default function AdminInvestmentRejectInput() {
<> <>
<ViewWrapper <ViewWrapper
footerComponent={buttonSubmit} footerComponent={buttonSubmit}
headerComponent={<AdminBackButtonAntTitle title="Penolakan Investasi" />} headerComponent={
<AdminBackButtonAntTitle title="Penolakan Investasi" />
}
> >
<TextAreaCustom <TextAreaCustom
value={value} value={value}

View File

@@ -1,69 +1,114 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { import {
ActionIcon, ActionIcon,
LoaderCustom,
SearchInput, SearchInput,
Spacing, StackCustom,
TextCustom, TextCustom,
ViewWrapper ViewWrapper
} from "@/components"; } from "@/components";
import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage"; import AdminComp_BoxTitle from "@/components/_ShareComponent/Admin/BoxTitlePage";
import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle"; import AdminTitleTable from "@/components/_ShareComponent/Admin/TableTitle";
import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue"; import AdminTableValue from "@/components/_ShareComponent/Admin/TableValue";
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
import NoDataText from "@/components/_ShareComponent/NoDataText";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value"; import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { apiAdminInvestment } from "@/service/api-admin/api-admin-investment";
import { Octicons } from "@expo/vector-icons"; import { Octicons } from "@expo/vector-icons";
import { router, useLocalSearchParams } from "expo-router"; import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash"; import _ from "lodash";
import React, { useCallback } from "react";
import { Divider } from "react-native-paper"; 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 [loadData, setLoadingData] = React.useState(false);
const [search, setSearch] = React.useState("");
useFocusEffect(
useCallback(() => {
onLoadData();
}, [status, search])
);
const onLoadData = async () => {
try {
setLoadingData(true);
const response = await apiAdminInvestment({
category: status as "publish" | "review" | "reject",
search,
});
console.log("[LIST DATA]", JSON.stringify(response, null, 2));
if (response.success) {
setListData(response.data);
}
} catch (error) {
console.log(error);
setListData([]);
} finally {
setLoadingData(false);
}
};
const rightComponent = ( const rightComponent = (
<SearchInput <SearchInput
containerStyle={{ width: "100%", marginBottom: 0 }} containerStyle={{ width: "100%", marginBottom: 0 }}
placeholder="Cari" placeholder="Cari"
value={search}
onChangeText={setSearch}
/> />
); );
return ( return (
<> <>
<ViewWrapper <ViewWrapper headerComponent={<AdminTitlePage title="Investasi" />}>
headerComponent={ <StackCustom gap={"sm"}>
<AdminComp_BoxTitle <AdminComp_BoxTitle
title={`Investasi ${_.startCase(status as string)}`} title={`${_.startCase(status as string)}`}
rightComponent={rightComponent} rightComponent={rightComponent}
/> />
}
>
<AdminTitleTable <AdminTitleTable
title1="Aksi" title1="Aksi"
title2="Username" title2="Username"
title3="Judul Investasi" title3="Judul Investasi"
/> />
<Spacing />
<Divider /> <Divider />
{Array.from({ length: 10 }).map((_, index) => ( {loadData ? (
<LoaderCustom />
) : _.isEmpty(listData) ? (
<NoDataText />
) : (
listData?.map((item: any, index: number) => (
<AdminTableValue <AdminTableValue
key={index} key={index}
value1={ value1={
<ActionIcon <ActionIcon
icon={ icon={
<Octicons name="eye" size={ICON_SIZE_BUTTON} color="black" /> <Octicons
name="eye"
size={ICON_SIZE_BUTTON}
color="black"
/>
} }
onPress={() => { onPress={() => {
router.push(`/admin/investment/${index}/${status}`); router.push(`/admin/investment/${item.id}/${status}`);
}} }}
/> />
} }
value2={<TextCustom truncate={1}>Username username</TextCustom>} value2={<TextCustom truncate={1}>{item?.author?.username}</TextCustom>}
value3={ value3={
<TextCustom truncate={2}> <TextCustom truncate={2}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. {item?.title}
Blanditiis asperiores quidem deleniti architecto eaque et
nostrum, ad consequuntur eveniet quisquam quae voluptatum
ducimus! Dolorem nobis modi officia debitis, beatae mollitia.
</TextCustom> </TextCustom>
} }
/> />
))} ))
)}
</StackCustom>
</ViewWrapper> </ViewWrapper>
</> </>
); );

View File

@@ -7,8 +7,51 @@ import {
import AdminComp_BoxDashboard from "@/components/_ShareComponent/Admin/BoxDashboard"; import AdminComp_BoxDashboard from "@/components/_ShareComponent/Admin/BoxDashboard";
import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage"; import AdminTitlePage from "@/components/_ShareComponent/Admin/TitlePage";
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
import { apiAdminInvestment } from "@/service/api-admin/api-admin-investment";
import { useFocusEffect } from "expo-router";
import React, { useCallback } from "react";
export default function AdminInvestment() { export default function AdminInvestment() {
const [data, setData] = React.useState<any | null>(null);
useFocusEffect(
useCallback(() => {
onLoadData();
}, [])
);
const onLoadData = async () => {
try {
const response = await apiAdminInvestment({
category: "dashboard",
});
console.log(JSON.stringify(response, null, 2));
if (response.success) {
setData(response.data);
}
} catch (error) {
console.log(error);
}
};
const listData = [
{
label: "Publish",
value: (data && data.publish) || 0,
icon: <IconPublish size={25} color={MainColor.green} />,
},
{
label: "Review",
value: (data && data.review) || 0,
icon: <IconReview size={25} color={MainColor.orange} />,
},
{
label: "Reject",
value: (data && data.reject) || 0,
icon: <IconReject size={25} color={MainColor.red} />,
},
];
return ( return (
<> <>
<ViewWrapper> <ViewWrapper>
@@ -23,21 +66,3 @@ export default function AdminInvestment() {
</> </>
); );
} }
const listData = [
{
label: "Publish",
value: 3,
icon: <IconPublish size={25} color={MainColor.green} />,
},
{
label: "Review",
value: 5,
icon: <IconReview size={25} color={MainColor.orange} />,
},
{
label: "Reject",
value: 8,
icon: <IconReject size={25} color={MainColor.red} />,
},
];

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 509 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 509 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 509 KiB

View File

@@ -19,8 +19,9 @@
"expo": "^54.0.0", "expo": "^54.0.0",
"expo-camera": "~17.0.7", "expo-camera": "~17.0.7",
"expo-clipboard": "~8.0.7", "expo-clipboard": "~8.0.7",
"expo-constants": "~18.0.8", "expo-constants": "^18.0.10",
"expo-dev-client": "~6.0.12", "expo-dev-client": "~6.0.12",
"expo-device": "^8.0.9",
"expo-document-picker": "~14.0.7", "expo-document-picker": "~14.0.7",
"expo-file-system": "^19.0.15", "expo-file-system": "^19.0.15",
"expo-font": "~14.0.8", "expo-font": "~14.0.8",
@@ -28,12 +29,13 @@
"expo-image": "~3.0.8", "expo-image": "~3.0.8",
"expo-image-picker": "~17.0.8", "expo-image-picker": "~17.0.8",
"expo-linking": "~8.0.8", "expo-linking": "~8.0.8",
"expo-notifications": "^0.32.13",
"expo-router": "~6.0.1", "expo-router": "~6.0.1",
"expo-splash-screen": "~31.0.9", "expo-splash-screen": "~31.0.9",
"expo-status-bar": "~3.0.8", "expo-status-bar": "~3.0.8",
"expo-symbols": "~1.0.7", "expo-symbols": "~1.0.7",
"expo-system-ui": "~6.0.7", "expo-system-ui": "~6.0.7",
"expo-web-browser": "~15.0.7", "expo-web-browser": "~15.0.9",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"react": "19.1.0", "react": "19.1.0",
"react-dom": "19.1.0", "react-dom": "19.1.0",
@@ -416,6 +418,8 @@
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
"@ide/backoff": ["@ide/backoff@1.0.0", "", {}, "sha512-F0YfUDjvT+Mtt/R4xdl2X0EYCHMMiJqNLdxHD++jDT5ydEFIyqbCHh51Qx2E211dgZprPKhV7sHmnXKpLuvc5g=="],
"@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="], "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
@@ -800,6 +804,8 @@
"asap": ["asap@2.0.6", "", {}, "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="], "asap": ["asap@2.0.6", "", {}, "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="],
"assert": ["assert@2.1.0", "", { "dependencies": { "call-bind": "^1.0.2", "is-nan": "^1.3.2", "object-is": "^1.1.5", "object.assign": "^4.1.4", "util": "^0.12.5" } }, "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw=="],
"async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="],
"async-limiter": ["async-limiter@1.0.1", "", {}, "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="], "async-limiter": ["async-limiter@1.0.1", "", {}, "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="],
@@ -838,6 +844,8 @@
"babel-preset-jest": ["babel-preset-jest@29.6.3", "", { "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA=="], "babel-preset-jest": ["babel-preset-jest@29.6.3", "", { "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA=="],
"badgin": ["badgin@1.2.3", "", {}, "sha512-NQGA7LcfCpSzIbGRbkgjgdWkjy7HI+Th5VLxTJfW5EeaAf3fnS+xWQaQOCYiny+q6QSvxqoSO04vCx+4u++EJw=="],
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
@@ -1150,13 +1158,15 @@
"expo": ["expo@54.0.2", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "54.0.2", "@expo/config": "~12.0.8", "@expo/config-plugins": "~54.0.1", "@expo/devtools": "0.1.7", "@expo/fingerprint": "0.15.0", "@expo/metro": "~0.1.1", "@expo/metro-config": "54.0.2", "@expo/vector-icons": "^15.0.2", "@ungap/structured-clone": "^1.3.0", "babel-preset-expo": "~54.0.0", "expo-asset": "~12.0.8", "expo-constants": "~18.0.8", "expo-file-system": "~19.0.12", "expo-font": "~14.0.8", "expo-keep-awake": "~15.0.7", "expo-modules-autolinking": "3.0.10", "expo-modules-core": "3.0.15", "pretty-format": "^29.7.0", "react-refresh": "^0.14.2", "whatwg-url-without-unicode": "8.0.0-3" }, "peerDependencies": { "@expo/dom-webview": "*", "@expo/metro-runtime": "*", "react": "*", "react-native": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/dom-webview", "@expo/metro-runtime", "react-native-webview"], "bin": { "expo": "bin/cli", "fingerprint": "bin/fingerprint", "expo-modules-autolinking": "bin/autolinking" } }, "sha512-0YcsvMuiZlVFVZRdD4PlhwsYrTmcN1qm5b1IRSLIeLZjH6ZnQwBb3KBSnK8WRC9V6EUPSbuLGpNT5AEewrtakQ=="], "expo": ["expo@54.0.2", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "54.0.2", "@expo/config": "~12.0.8", "@expo/config-plugins": "~54.0.1", "@expo/devtools": "0.1.7", "@expo/fingerprint": "0.15.0", "@expo/metro": "~0.1.1", "@expo/metro-config": "54.0.2", "@expo/vector-icons": "^15.0.2", "@ungap/structured-clone": "^1.3.0", "babel-preset-expo": "~54.0.0", "expo-asset": "~12.0.8", "expo-constants": "~18.0.8", "expo-file-system": "~19.0.12", "expo-font": "~14.0.8", "expo-keep-awake": "~15.0.7", "expo-modules-autolinking": "3.0.10", "expo-modules-core": "3.0.15", "pretty-format": "^29.7.0", "react-refresh": "^0.14.2", "whatwg-url-without-unicode": "8.0.0-3" }, "peerDependencies": { "@expo/dom-webview": "*", "@expo/metro-runtime": "*", "react": "*", "react-native": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/dom-webview", "@expo/metro-runtime", "react-native-webview"], "bin": { "expo": "bin/cli", "fingerprint": "bin/fingerprint", "expo-modules-autolinking": "bin/autolinking" } }, "sha512-0YcsvMuiZlVFVZRdD4PlhwsYrTmcN1qm5b1IRSLIeLZjH6ZnQwBb3KBSnK8WRC9V6EUPSbuLGpNT5AEewrtakQ=="],
"expo-application": ["expo-application@7.0.7", "", { "peerDependencies": { "expo": "*" } }, "sha512-Jt1/qqnoDUbZ+bK91+dHaZ1vrPDtRBOltRa681EeedkisqguuEeUx4UHqwVyDK2oHWsK6lO3ojetoA4h8OmNcg=="],
"expo-asset": ["expo-asset@12.0.8", "", { "dependencies": { "@expo/image-utils": "^0.8.7", "expo-constants": "~18.0.8" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-jj2U8zw9+7orST2rlQGULYiqPoECOuUyffs2NguGrq84bYbkM041T7TOMXH2raPVJnM9lEAP54ezI6XL+GVYqw=="], "expo-asset": ["expo-asset@12.0.8", "", { "dependencies": { "@expo/image-utils": "^0.8.7", "expo-constants": "~18.0.8" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-jj2U8zw9+7orST2rlQGULYiqPoECOuUyffs2NguGrq84bYbkM041T7TOMXH2raPVJnM9lEAP54ezI6XL+GVYqw=="],
"expo-camera": ["expo-camera@17.0.7", "", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-jdZfijfFjlVAuuIkDheA41YKpigPjqsN0juRvgyr7Lcyz+fvwZ3/RP50/n/hvuozH657wHxPfiyVVFa00z8TcQ=="], "expo-camera": ["expo-camera@17.0.7", "", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-jdZfijfFjlVAuuIkDheA41YKpigPjqsN0juRvgyr7Lcyz+fvwZ3/RP50/n/hvuozH657wHxPfiyVVFa00z8TcQ=="],
"expo-clipboard": ["expo-clipboard@8.0.7", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-zvlfFV+wB2QQrQnHWlo0EKHAkdi2tycLtE+EXFUWTPZYkgu1XcH+aiKfd4ul7Z0SDF+1IuwoiW9AA9eO35aj3Q=="], "expo-clipboard": ["expo-clipboard@8.0.7", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-zvlfFV+wB2QQrQnHWlo0EKHAkdi2tycLtE+EXFUWTPZYkgu1XcH+aiKfd4ul7Z0SDF+1IuwoiW9AA9eO35aj3Q=="],
"expo-constants": ["expo-constants@18.0.8", "", { "dependencies": { "@expo/config": "~12.0.8", "@expo/env": "~2.0.7" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-Tetphsx6RVImCTZeBAclRQMy0WOODY3y6qrUoc88YGUBVm8fAKkErCSWxLTCc6nFcJxdoOMYi62LgNIUFjZCLA=="], "expo-constants": ["expo-constants@18.0.10", "", { "dependencies": { "@expo/config": "~12.0.10", "@expo/env": "~2.0.7" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-Rhtv+X974k0Cahmvx6p7ER5+pNhBC0XbP1lRviL2J1Xl4sT2FBaIuIxF/0I0CbhOsySf0ksqc5caFweAy9Ewiw=="],
"expo-dev-client": ["expo-dev-client@6.0.12", "", { "dependencies": { "expo-dev-launcher": "6.0.11", "expo-dev-menu": "7.0.11", "expo-dev-menu-interface": "2.0.0", "expo-manifests": "~1.0.8", "expo-updates-interface": "~2.0.0" }, "peerDependencies": { "expo": "*" } }, "sha512-Knr2abq0r6ALASsZtrX9QD4V0vP4ZL18iDVF5lgr6iFYawbuqQHuJRktIUETimu6qLusJK8Z3kZRabAdNqT+qw=="], "expo-dev-client": ["expo-dev-client@6.0.12", "", { "dependencies": { "expo-dev-launcher": "6.0.11", "expo-dev-menu": "7.0.11", "expo-dev-menu-interface": "2.0.0", "expo-manifests": "~1.0.8", "expo-updates-interface": "~2.0.0" }, "peerDependencies": { "expo": "*" } }, "sha512-Knr2abq0r6ALASsZtrX9QD4V0vP4ZL18iDVF5lgr6iFYawbuqQHuJRktIUETimu6qLusJK8Z3kZRabAdNqT+qw=="],
@@ -1166,6 +1176,8 @@
"expo-dev-menu-interface": ["expo-dev-menu-interface@2.0.0", "", { "peerDependencies": { "expo": "*" } }, "sha512-BvAMPt6x+vyXpThsyjjOYyjwfjREV4OOpQkZ0tNl+nGpsPfcY9mc6DRACoWnH9KpLzyIt3BOgh3cuy/h/OxQjw=="], "expo-dev-menu-interface": ["expo-dev-menu-interface@2.0.0", "", { "peerDependencies": { "expo": "*" } }, "sha512-BvAMPt6x+vyXpThsyjjOYyjwfjREV4OOpQkZ0tNl+nGpsPfcY9mc6DRACoWnH9KpLzyIt3BOgh3cuy/h/OxQjw=="],
"expo-device": ["expo-device@8.0.9", "", { "dependencies": { "ua-parser-js": "^0.7.33" }, "peerDependencies": { "expo": "*" } }, "sha512-XqRpaljDNAYZGZzMpC+b9KZfzfydtkwx3pJAp6ODDH+O/5wjAw+mLc5wQMGJCx8/aqVmMsAokec7iebxDPFZDA=="],
"expo-document-picker": ["expo-document-picker@14.0.7", "", { "peerDependencies": { "expo": "*" } }, "sha512-81Jh8RDD0GYBUoSTmIBq30hXXjmkDV1ZY2BNIp1+3HR5PDSh2WmdhD/Ezz5YFsv46hIXHsQc+Kh1q8vn6OLT9Q=="], "expo-document-picker": ["expo-document-picker@14.0.7", "", { "peerDependencies": { "expo": "*" } }, "sha512-81Jh8RDD0GYBUoSTmIBq30hXXjmkDV1ZY2BNIp1+3HR5PDSh2WmdhD/Ezz5YFsv46hIXHsQc+Kh1q8vn6OLT9Q=="],
"expo-file-system": ["expo-file-system@19.0.15", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-sRLW+3PVJDiuoCE2LuteHhC7OxPjh1cfqLylf1YG1TDEbbQXnzwjfsKeRm6dslEPZLkMWfSLYIrVbnuq5mF7kQ=="], "expo-file-system": ["expo-file-system@19.0.15", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-sRLW+3PVJDiuoCE2LuteHhC7OxPjh1cfqLylf1YG1TDEbbQXnzwjfsKeRm6dslEPZLkMWfSLYIrVbnuq5mF7kQ=="],
@@ -1194,6 +1206,8 @@
"expo-modules-core": ["expo-modules-core@3.0.15", "", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-vGI7osd0/IjprldD08k4bckWSu7ID4HhZNP68l/UtilONQ8XZig8mWJd/Fm7i7KGvE3HyuF+HOXE9l671no42Q=="], "expo-modules-core": ["expo-modules-core@3.0.15", "", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-vGI7osd0/IjprldD08k4bckWSu7ID4HhZNP68l/UtilONQ8XZig8mWJd/Fm7i7KGvE3HyuF+HOXE9l671no42Q=="],
"expo-notifications": ["expo-notifications@0.32.13", "", { "dependencies": { "@expo/image-utils": "^0.8.7", "@ide/backoff": "^1.0.0", "abort-controller": "^3.0.0", "assert": "^2.0.0", "badgin": "^1.1.5", "expo-application": "~7.0.7", "expo-constants": "~18.0.10" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-PL0R1ulLVUgAswlXtRDKxBlcipNM3YA6+P5nB5JIhXbsjLJ7y+EKVaEhHhbaGzuK1QVsRQSJNm/4oISX+vsmFQ=="],
"expo-router": ["expo-router@6.0.1", "", { "dependencies": { "@expo/metro-runtime": "6.1.1", "@expo/schema-utils": "^0.1.7", "@expo/server": "^0.7.4", "@radix-ui/react-slot": "1.2.0", "@radix-ui/react-tabs": "^1.1.12", "@react-navigation/bottom-tabs": "^7.4.0", "@react-navigation/native": "^7.1.8", "@react-navigation/native-stack": "^7.3.16", "client-only": "^0.0.1", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "invariant": "^2.2.4", "nanoid": "^3.3.8", "query-string": "^7.1.3", "react-fast-compare": "^3.2.2", "react-native-is-edge-to-edge": "^1.1.6", "semver": "~7.6.3", "server-only": "^0.0.1", "sf-symbols-typescript": "^2.1.0", "shallowequal": "^1.1.0", "use-latest-callback": "^0.2.1", "vaul": "^1.1.2" }, "peerDependencies": { "@react-navigation/drawer": "^7.5.0", "@testing-library/react-native": ">= 12.0.0", "expo": "*", "expo-constants": "^18.0.8", "expo-linking": "^8.0.8", "react": "*", "react-dom": "*", "react-native": "*", "react-native-gesture-handler": "*", "react-native-reanimated": "*", "react-native-safe-area-context": ">= 5.4.0", "react-native-screens": "*", "react-native-web": "*", "react-server-dom-webpack": ">= 19.0.0" }, "optionalPeers": ["@react-navigation/drawer", "@testing-library/react-native", "react-dom", "react-native-gesture-handler", "react-native-reanimated", "react-native-web", "react-server-dom-webpack"] }, "sha512-5wXkWyNMqUbjCWH0PRkOM0P6UsgLVdgchDkiLz5FY7HfU00ToBcxij965bqtlaATBgoaIo4DuLu6EgxewrKJ8Q=="], "expo-router": ["expo-router@6.0.1", "", { "dependencies": { "@expo/metro-runtime": "6.1.1", "@expo/schema-utils": "^0.1.7", "@expo/server": "^0.7.4", "@radix-ui/react-slot": "1.2.0", "@radix-ui/react-tabs": "^1.1.12", "@react-navigation/bottom-tabs": "^7.4.0", "@react-navigation/native": "^7.1.8", "@react-navigation/native-stack": "^7.3.16", "client-only": "^0.0.1", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "invariant": "^2.2.4", "nanoid": "^3.3.8", "query-string": "^7.1.3", "react-fast-compare": "^3.2.2", "react-native-is-edge-to-edge": "^1.1.6", "semver": "~7.6.3", "server-only": "^0.0.1", "sf-symbols-typescript": "^2.1.0", "shallowequal": "^1.1.0", "use-latest-callback": "^0.2.1", "vaul": "^1.1.2" }, "peerDependencies": { "@react-navigation/drawer": "^7.5.0", "@testing-library/react-native": ">= 12.0.0", "expo": "*", "expo-constants": "^18.0.8", "expo-linking": "^8.0.8", "react": "*", "react-dom": "*", "react-native": "*", "react-native-gesture-handler": "*", "react-native-reanimated": "*", "react-native-safe-area-context": ">= 5.4.0", "react-native-screens": "*", "react-native-web": "*", "react-server-dom-webpack": ">= 19.0.0" }, "optionalPeers": ["@react-navigation/drawer", "@testing-library/react-native", "react-dom", "react-native-gesture-handler", "react-native-reanimated", "react-native-web", "react-server-dom-webpack"] }, "sha512-5wXkWyNMqUbjCWH0PRkOM0P6UsgLVdgchDkiLz5FY7HfU00ToBcxij965bqtlaATBgoaIo4DuLu6EgxewrKJ8Q=="],
"expo-splash-screen": ["expo-splash-screen@31.0.9", "", { "dependencies": { "@expo/prebuild-config": "^54.0.1" }, "peerDependencies": { "expo": "*" } }, "sha512-pYLWFrEHn/c8e1a8oDzrlcyYI08oG4i37KA+VN5wwoC1DsQ0rm3kyAk0bmoydV1mBzNfXQFYbA1BGftXJl1f0w=="], "expo-splash-screen": ["expo-splash-screen@31.0.9", "", { "dependencies": { "@expo/prebuild-config": "^54.0.1" }, "peerDependencies": { "expo": "*" } }, "sha512-pYLWFrEHn/c8e1a8oDzrlcyYI08oG4i37KA+VN5wwoC1DsQ0rm3kyAk0bmoydV1mBzNfXQFYbA1BGftXJl1f0w=="],
@@ -1206,7 +1220,7 @@
"expo-updates-interface": ["expo-updates-interface@2.0.0", "", { "peerDependencies": { "expo": "*" } }, "sha512-pTzAIufEZdVPKql6iMi5ylVSPqV1qbEopz9G6TSECQmnNde2nwq42PxdFBaUEd8IZJ/fdJLQnOT3m6+XJ5s7jg=="], "expo-updates-interface": ["expo-updates-interface@2.0.0", "", { "peerDependencies": { "expo": "*" } }, "sha512-pTzAIufEZdVPKql6iMi5ylVSPqV1qbEopz9G6TSECQmnNde2nwq42PxdFBaUEd8IZJ/fdJLQnOT3m6+XJ5s7jg=="],
"expo-web-browser": ["expo-web-browser@15.0.7", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-eXnfO3FQ2WthTA8uEPNJ7SDRfPaLIU/P2k082HGEYIHAFZMwh2o9Wo+SDVytO3E95TAv1qwhggUjOrczYzxteQ=="], "expo-web-browser": ["expo-web-browser@15.0.9", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-Dj8kNFO+oXsxqCDNlUT/GhOrJnm10kAElH++3RplLydogFm5jTzXYWDEeNIDmV+F+BzGYs+sIhxiBf7RyaxXZg=="],
"exponential-backoff": ["exponential-backoff@3.1.2", "", {}, "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA=="], "exponential-backoff": ["exponential-backoff@3.1.2", "", {}, "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA=="],
@@ -1378,6 +1392,8 @@
"invariant": ["invariant@2.2.4", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="], "invariant": ["invariant@2.2.4", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="],
"is-arguments": ["is-arguments@1.2.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA=="],
"is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="], "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="],
"is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="], "is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="],
@@ -1418,6 +1434,8 @@
"is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="], "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="],
"is-nan": ["is-nan@1.3.2", "", { "dependencies": { "call-bind": "^1.0.0", "define-properties": "^1.1.3" } }, "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w=="],
"is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="], "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="],
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
@@ -1724,6 +1742,8 @@
"object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
"object-is": ["object-is@1.1.6", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1" } }, "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q=="],
"object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="], "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="],
"object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="], "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="],
@@ -2180,7 +2200,7 @@
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
"ua-parser-js": ["ua-parser-js@1.0.40", "", { "bin": "script/cli.js" }, "sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew=="], "ua-parser-js": ["ua-parser-js@0.7.41", "", { "bin": { "ua-parser-js": "script/cli.js" } }, "sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg=="],
"unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
@@ -2218,6 +2238,8 @@
"use-sync-external-store": ["use-sync-external-store@1.5.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A=="], "use-sync-external-store": ["use-sync-external-store@1.5.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A=="],
"util": ["util@0.12.5", "", { "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", "which-typed-array": "^1.1.2" } }, "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA=="],
"utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="],
"uuid": ["uuid@7.0.3", "", { "bin": "dist/bin/uuid" }, "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="], "uuid": ["uuid@7.0.3", "", { "bin": "dist/bin/uuid" }, "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="],
@@ -2564,8 +2586,16 @@
"expo/babel-preset-expo": ["babel-preset-expo@54.0.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-transform-class-static-block": "^7.27.1", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@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-runtime": "^7.24.7", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.0", "@react-native/babel-preset": "0.81.4", "babel-plugin-react-compiler": "^19.1.0-rc.2", "babel-plugin-react-native-web": "~0.21.0", "babel-plugin-syntax-hermes-parser": "^0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4", "resolve-from": "^5.0.0" }, "peerDependencies": { "@babel/runtime": "^7.20.0", "expo": "*", "react-refresh": ">=0.14.0 <1.0.0" }, "optionalPeers": ["@babel/runtime", "expo"] }, "sha512-a0Ej4ik6xzvtrA4Ivblov3XVvfntIoqnXOy2jG2k/3hzWqzrJxKyY2gUW9ZCMAicGevj2ju28q+TsK29uTe0eQ=="], "expo/babel-preset-expo": ["babel-preset-expo@54.0.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-transform-class-static-block": "^7.27.1", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@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-runtime": "^7.24.7", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.0", "@react-native/babel-preset": "0.81.4", "babel-plugin-react-compiler": "^19.1.0-rc.2", "babel-plugin-react-native-web": "~0.21.0", "babel-plugin-syntax-hermes-parser": "^0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4", "resolve-from": "^5.0.0" }, "peerDependencies": { "@babel/runtime": "^7.20.0", "expo": "*", "react-refresh": ">=0.14.0 <1.0.0" }, "optionalPeers": ["@babel/runtime", "expo"] }, "sha512-a0Ej4ik6xzvtrA4Ivblov3XVvfntIoqnXOy2jG2k/3hzWqzrJxKyY2gUW9ZCMAicGevj2ju28q+TsK29uTe0eQ=="],
"expo/expo-constants": ["expo-constants@18.0.8", "", { "dependencies": { "@expo/config": "~12.0.8", "@expo/env": "~2.0.7" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-Tetphsx6RVImCTZeBAclRQMy0WOODY3y6qrUoc88YGUBVm8fAKkErCSWxLTCc6nFcJxdoOMYi62LgNIUFjZCLA=="],
"expo/expo-file-system": ["expo-file-system@19.0.12", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-gqpxpnjfhzXLcqMOi49isB5S1Af49P9410fsaFfnLZWN3X6Dwc8EplDwbaolOI/wnGwP81P+/nDn5RNmU6m7mQ=="], "expo/expo-file-system": ["expo-file-system@19.0.12", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-gqpxpnjfhzXLcqMOi49isB5S1Af49P9410fsaFfnLZWN3X6Dwc8EplDwbaolOI/wnGwP81P+/nDn5RNmU6m7mQ=="],
"expo-asset/expo-constants": ["expo-constants@18.0.8", "", { "dependencies": { "@expo/config": "~12.0.8", "@expo/env": "~2.0.7" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-Tetphsx6RVImCTZeBAclRQMy0WOODY3y6qrUoc88YGUBVm8fAKkErCSWxLTCc6nFcJxdoOMYi62LgNIUFjZCLA=="],
"expo-constants/@expo/config": ["@expo/config@12.0.10", "", { "dependencies": { "@babel/code-frame": "~7.10.4", "@expo/config-plugins": "~54.0.2", "@expo/config-types": "^54.0.8", "@expo/json-file": "^10.0.7", "deepmerge": "^4.3.1", "getenv": "^2.0.0", "glob": "^10.4.2", "require-from-string": "^2.0.2", "resolve-from": "^5.0.0", "resolve-workspace-root": "^2.0.0", "semver": "^7.6.0", "slugify": "^1.3.4", "sucrase": "3.35.0" } }, "sha512-lJMof5Nqakq1DxGYlghYB/ogSBjmv4Fxn1ovyDmcjlRsQdFCXgu06gEUogkhPtc9wBt9WlTTfqENln5HHyLW6w=="],
"expo-linking/expo-constants": ["expo-constants@18.0.8", "", { "dependencies": { "@expo/config": "~12.0.8", "@expo/env": "~2.0.7" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-Tetphsx6RVImCTZeBAclRQMy0WOODY3y6qrUoc88YGUBVm8fAKkErCSWxLTCc6nFcJxdoOMYi62LgNIUFjZCLA=="],
"expo-module-scripts/typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], "expo-module-scripts/typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
"expo-modules-autolinking/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], "expo-modules-autolinking/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
@@ -2578,6 +2608,8 @@
"fbjs/promise": ["promise@7.3.1", "", { "dependencies": { "asap": "~2.0.3" } }, "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="], "fbjs/promise": ["promise@7.3.1", "", { "dependencies": { "asap": "~2.0.3" } }, "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="],
"fbjs/ua-parser-js": ["ua-parser-js@1.0.40", "", { "bin": "script/cli.js" }, "sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew=="],
"finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
"finalhandler/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], "finalhandler/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="],
@@ -2946,6 +2978,14 @@
"expect/jest-matcher-utils/jest-diff": ["jest-diff@29.7.0", "", { "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", "jest-get-type": "^29.6.3", "pretty-format": "^29.7.0" } }, "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw=="], "expect/jest-matcher-utils/jest-diff": ["jest-diff@29.7.0", "", { "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.6.3", "jest-get-type": "^29.6.3", "pretty-format": "^29.7.0" } }, "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw=="],
"expo-constants/@expo/config/@babel/code-frame": ["@babel/code-frame@7.10.4", "", { "dependencies": { "@babel/highlight": "^7.10.4" } }, "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg=="],
"expo-constants/@expo/config/@expo/config-plugins": ["@expo/config-plugins@54.0.2", "", { "dependencies": { "@expo/config-types": "^54.0.8", "@expo/json-file": "~10.0.7", "@expo/plist": "^0.4.7", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", "getenv": "^2.0.0", "glob": "^10.4.2", "resolve-from": "^5.0.0", "semver": "^7.5.4", "slash": "^3.0.0", "slugify": "^1.6.6", "xcode": "^3.0.1", "xml2js": "0.6.0" } }, "sha512-jD4qxFcURQUVsUFGMcbo63a/AnviK8WUGard+yrdQE3ZrB/aurn68SlApjirQQLEizhjI5Ar2ufqflOBlNpyPg=="],
"expo-constants/@expo/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-constants/@expo/config/semver": ["semver@7.7.2", "", { "bin": "bin/semver.js" }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
"expo/babel-preset-expo/@react-native/babel-preset": ["@react-native/babel-preset@0.81.4", "", { "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.81.4", "babel-plugin-syntax-hermes-parser": "0.29.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-VYj0c/cTjQJn/RJ5G6P0L9wuYSbU9yGbPYDHCKstlQZQWkk+L9V8ZDbxdJBTIei9Xl3KPQ1odQ4QaeW+4v+AZg=="], "expo/babel-preset-expo/@react-native/babel-preset": ["@react-native/babel-preset@0.81.4", "", { "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.81.4", "babel-plugin-syntax-hermes-parser": "0.29.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-VYj0c/cTjQJn/RJ5G6P0L9wuYSbU9yGbPYDHCKstlQZQWkk+L9V8ZDbxdJBTIei9Xl3KPQ1odQ4QaeW+4v+AZg=="],
"expo/babel-preset-expo/babel-plugin-react-native-web": ["babel-plugin-react-native-web@0.21.1", "", {}, "sha512-7XywfJ5QIRMwjOL+pwJt2w47Jmi5fFLvK7/So4fV4jIN6PcRbylCp9/l3cJY4VJbSz3lnWTeHDTD1LKIc1C09Q=="], "expo/babel-preset-expo/babel-plugin-react-native-web": ["babel-plugin-react-native-web@0.21.1", "", {}, "sha512-7XywfJ5QIRMwjOL+pwJt2w47Jmi5fFLvK7/So4fV4jIN6PcRbylCp9/l3cJY4VJbSz3lnWTeHDTD1LKIc1C09Q=="],
@@ -3128,6 +3168,8 @@
"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/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.81.4", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.81.4" } }, "sha512-6ztXf2Tl2iWznyI/Da/N2Eqymt0Mnn69GCLnEFxFbNdk0HxHPZBNWU9shTXhsLWOL7HATSqwg/bB1+3kY1q+mA=="], "expo/babel-preset-expo/@react-native/babel-preset/@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.81.4", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.81.4" } }, "sha512-6ztXf2Tl2iWznyI/Da/N2Eqymt0Mnn69GCLnEFxFbNdk0HxHPZBNWU9shTXhsLWOL7HATSqwg/bB1+3kY1q+mA=="],
"expo/babel-preset-expo/@react-native/babel-preset/babel-plugin-syntax-hermes-parser": ["babel-plugin-syntax-hermes-parser@0.29.1", "", { "dependencies": { "hermes-parser": "0.29.1" } }, "sha512-2WFYnoWGdmih1I1J5eIqxATOeycOqRwYxAQBu3cUu/rhwInwHUg7k60AFNbuGjSDL8tje5GDrAnxzRLcu2pYcA=="], "expo/babel-preset-expo/@react-native/babel-preset/babel-plugin-syntax-hermes-parser": ["babel-plugin-syntax-hermes-parser@0.29.1", "", { "dependencies": { "hermes-parser": "0.29.1" } }, "sha512-2WFYnoWGdmih1I1J5eIqxATOeycOqRwYxAQBu3cUu/rhwInwHUg7k60AFNbuGjSDL8tje5GDrAnxzRLcu2pYcA=="],

View File

@@ -109,6 +109,7 @@ const styles = StyleSheet.create({
flexDirection: "row", flexDirection: "row",
flexWrap: "wrap", flexWrap: "wrap",
justifyContent: "flex-start", justifyContent: "flex-start",
marginInline: 0.1 // marginInline: 0.1
margin: 0.1
}, },
}); });

View File

@@ -0,0 +1,9 @@
import TextCustom from "../Text/TextCustom";
export default function NoDataText({ text }: { text?: string }) {
return (
<TextCustom color="gray" align="center" bold size={"small"}>
{text ? text : "Belum ada data"}
</TextCustom>
);
}

View File

@@ -1,7 +1,7 @@
{ {
"cli": { "cli": {
"version": ">= 16.10.0", "version": ">= 16.10.0",
"appVersionSource": "remote" "appVersionSource": "local"
}, },
"build": { "build": {
"development": { "development": {
@@ -11,11 +11,19 @@
"preview": { "preview": {
"distribution": "internal", "distribution": "internal",
"android": { "android": {
"buildType": "apk" "buildType": "app-bundle"
},
"ios": {
"simulator": false
} }
}, },
"production": { "production": {
"autoIncrement": true "android": {
"buildType": "app-bundle"
},
"ios": {
"resourceClass": "m1-medium"
}
} }
}, },
"submit": { "submit": {

29
google-services.json Normal file
View File

@@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "608461535079",
"project_id": "hipmi-badung-connect",
"storage_bucket": "hipmi-badung-connect.firebasestorage.app"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:608461535079:android:4ff12ddc283fb3746761c2",
"android_client_info": {
"package_name": "com.bip.hipmimobileapp"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyBiDtIk3Q9zffFwIdJ5cjqY7e4390JGSkM"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}

15
hipmi-note.md Normal file
View File

@@ -0,0 +1,15 @@
### Buil
eas build --profile production : for build production on expo with eas
npx expo prebuild : untuk build dan membuat folder android & ios
open ios/<nama-app>.xcworkspace : untuk membuka file xcode
Build ios : bun run ios
Build android : bun run android
Exp: open ios/HIPMIBADUNG.xcworkspace
### Other
perubahan versi : npm version patch
ios: bunx expo prebuild --platform ios
android: bunx expo prebuild --platform android

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
</plist>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

View File

@@ -8,20 +8,28 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
241CFEB1CBB2124E18A09822 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 51B6792712498367CD1EEA5D /* PrivacyInfo.xcprivacy */; };
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; }; 3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
7833AA2741E7B2CCBEBEB1C7 /* libPods-HIPMIBadungConnect.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B3A38F3F981E3720B61AC51 /* libPods-HIPMIBadungConnect.a */; };
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; }; BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
D138B3E4BC618ADDE62DCDCC /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8F39CC335B3942749573F05 /* ExpoModulesProvider.swift */; };
F11748422D0307B40044C1D9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11748412D0307B40044C1D9 /* AppDelegate.swift */; }; F11748422D0307B40044C1D9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11748412D0307B40044C1D9 /* AppDelegate.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
13B07F961A680F5B00A75B9A /* HIPMIBADUNG.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HIPMIBADUNG.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07F961A680F5B00A75B9A /* HIPMIBadungConnect.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HIPMIBadungConnect.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = HIPMIBADUNG/Images.xcassets; sourceTree = "<group>"; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = HIPMIBadungConnect/Images.xcassets; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = HIPMIBADUNG/Info.plist; sourceTree = "<group>"; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = HIPMIBadungConnect/Info.plist; sourceTree = "<group>"; };
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = HIPMIBADUNG/SplashScreen.storyboard; sourceTree = "<group>"; }; 1E94102500A8768C71C74AF6 /* Pods-HIPMIBadungConnect.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HIPMIBadungConnect.debug.xcconfig"; path = "Target Support Files/Pods-HIPMIBadungConnect/Pods-HIPMIBadungConnect.debug.xcconfig"; sourceTree = "<group>"; };
51B6792712498367CD1EEA5D /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = HIPMIBadungConnect/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
9B3A38F3F981E3720B61AC51 /* libPods-HIPMIBadungConnect.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HIPMIBadungConnect.a"; sourceTree = BUILT_PRODUCTS_DIR; };
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = HIPMIBadungConnect/SplashScreen.storyboard; sourceTree = "<group>"; };
BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = "<group>"; }; BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = "<group>"; };
C19B4954908DD0D4CD2965DF /* Pods-HIPMIBadungConnect.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HIPMIBadungConnect.release.xcconfig"; path = "Target Support Files/Pods-HIPMIBadungConnect/Pods-HIPMIBadungConnect.release.xcconfig"; sourceTree = "<group>"; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
F11748412D0307B40044C1D9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = HIPMIBADUNG/AppDelegate.swift; sourceTree = "<group>"; }; F11748412D0307B40044C1D9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = HIPMIBadungConnect/AppDelegate.swift; sourceTree = "<group>"; };
F11748442D0722820044C1D9 /* HIPMIBADUNG-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "HIPMIBADUNG-Bridging-Header.h"; path = "HIPMIBADUNG/HIPMIBADUNG-Bridging-Header.h"; sourceTree = "<group>"; }; F11748442D0722820044C1D9 /* HIPMIBadungConnect-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "HIPMIBadungConnect-Bridging-Header.h"; path = "HIPMIBadungConnect/HIPMIBadungConnect-Bridging-Header.h"; sourceTree = "<group>"; };
F8F39CC335B3942749573F05 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-HIPMIBadungConnect/ExpoModulesProvider.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@@ -29,33 +37,44 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
7833AA2741E7B2CCBEBEB1C7 /* libPods-HIPMIBadungConnect.a in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
13B07FAE1A68108700A75B9A /* HIPMIBADUNG */ = { 13B07FAE1A68108700A75B9A /* HIPMIBadungConnect */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
F11748412D0307B40044C1D9 /* AppDelegate.swift */, F11748412D0307B40044C1D9 /* AppDelegate.swift */,
F11748442D0722820044C1D9 /* HIPMIBADUNG-Bridging-Header.h */, F11748442D0722820044C1D9 /* HIPMIBadungConnect-Bridging-Header.h */,
BB2F792B24A3F905000567C9 /* Supporting */, BB2F792B24A3F905000567C9 /* Supporting */,
13B07FB51A68108700A75B9A /* Images.xcassets */, 13B07FB51A68108700A75B9A /* Images.xcassets */,
13B07FB61A68108700A75B9A /* Info.plist */, 13B07FB61A68108700A75B9A /* Info.plist */,
AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */, AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */,
51B6792712498367CD1EEA5D /* PrivacyInfo.xcprivacy */,
); );
name = HIPMIBADUNG; name = HIPMIBadungConnect;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
2D16E6871FA4F8E400B85C8A /* Frameworks */ = { 2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
ED297162215061F000B7C4FE /* JavaScriptCore.framework */, ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
9B3A38F3F981E3720B61AC51 /* libPods-HIPMIBadungConnect.a */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
6C62A8BDDB81F7BE378344ED /* ExpoModulesProviders */ = {
isa = PBXGroup;
children = (
C0BA0842F7555AB0104D3227 /* HIPMIBadungConnect */,
);
name = ExpoModulesProviders;
sourceTree = "<group>";
};
832341AE1AAA6A7D00B99B32 /* Libraries */ = { 832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@@ -66,10 +85,12 @@
83CBB9F61A601CBA00E9B192 = { 83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
13B07FAE1A68108700A75B9A /* HIPMIBADUNG */, 13B07FAE1A68108700A75B9A /* HIPMIBadungConnect */,
832341AE1AAA6A7D00B99B32 /* Libraries */, 832341AE1AAA6A7D00B99B32 /* Libraries */,
83CBBA001A601CBA00E9B192 /* Products */, 83CBBA001A601CBA00E9B192 /* Products */,
2D16E6871FA4F8E400B85C8A /* Frameworks */, 2D16E6871FA4F8E400B85C8A /* Frameworks */,
A30E580F1E4E26A6BD0E3B24 /* Pods */,
6C62A8BDDB81F7BE378344ED /* ExpoModulesProviders */,
); );
indentWidth = 2; indentWidth = 2;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -79,41 +100,60 @@
83CBBA001A601CBA00E9B192 /* Products */ = { 83CBBA001A601CBA00E9B192 /* Products */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
13B07F961A680F5B00A75B9A /* HIPMIBADUNG.app */, 13B07F961A680F5B00A75B9A /* HIPMIBadungConnect.app */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
A30E580F1E4E26A6BD0E3B24 /* Pods */ = {
isa = PBXGroup;
children = (
1E94102500A8768C71C74AF6 /* Pods-HIPMIBadungConnect.debug.xcconfig */,
C19B4954908DD0D4CD2965DF /* Pods-HIPMIBadungConnect.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
BB2F792B24A3F905000567C9 /* Supporting */ = { BB2F792B24A3F905000567C9 /* Supporting */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
BB2F792C24A3F905000567C9 /* Expo.plist */, BB2F792C24A3F905000567C9 /* Expo.plist */,
); );
name = Supporting; name = Supporting;
path = HIPMIBADUNG/Supporting; path = HIPMIBadungConnect/Supporting;
sourceTree = "<group>";
};
C0BA0842F7555AB0104D3227 /* HIPMIBadungConnect */ = {
isa = PBXGroup;
children = (
F8F39CC335B3942749573F05 /* ExpoModulesProvider.swift */,
);
name = HIPMIBadungConnect;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
13B07F861A680F5B00A75B9A /* HIPMIBADUNG */ = { 13B07F861A680F5B00A75B9A /* HIPMIBadungConnect */ = {
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "HIPMIBADUNG" */; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "HIPMIBadungConnect" */;
buildPhases = ( buildPhases = (
08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */, 08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */,
0B90913696EEE0E819CAF510 /* [Expo] Configure project */,
13B07F871A680F5B00A75B9A /* Sources */, 13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */, 13B07F8E1A680F5B00A75B9A /* Resources */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */, 800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */,
2DA25245F64078F29C0B38E4 /* [CP] Embed Pods Frameworks */,
); );
buildRules = ( buildRules = (
); );
dependencies = ( dependencies = (
); );
name = HIPMIBADUNG; name = HIPMIBadungConnect;
productName = HIPMIBADUNG; productName = HIPMIBadungConnect;
productReference = 13B07F961A680F5B00A75B9A /* HIPMIBADUNG.app */; productReference = 13B07F961A680F5B00A75B9A /* HIPMIBadungConnect.app */;
productType = "com.apple.product-type.application"; productType = "com.apple.product-type.application";
}; };
/* End PBXNativeTarget section */ /* End PBXNativeTarget section */
@@ -129,7 +169,7 @@
}; };
}; };
}; };
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "HIPMIBADUNG" */; buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "HIPMIBadungConnect" */;
compatibilityVersion = "Xcode 3.2"; compatibilityVersion = "Xcode 3.2";
developmentRegion = en; developmentRegion = en;
hasScannedForEncodings = 0; hasScannedForEncodings = 0;
@@ -142,7 +182,7 @@
projectDirPath = ""; projectDirPath = "";
projectRoot = ""; projectRoot = "";
targets = ( targets = (
13B07F861A680F5B00A75B9A /* HIPMIBADUNG */, 13B07F861A680F5B00A75B9A /* HIPMIBadungConnect */,
); );
}; };
/* End PBXProject section */ /* End PBXProject section */
@@ -155,6 +195,7 @@
BB2F792D24A3F905000567C9 /* Expo.plist in Resources */, BB2F792D24A3F905000567C9 /* Expo.plist in Resources */,
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */, 3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */,
241CFEB1CBB2124E18A09822 /* PrivacyInfo.xcprivacy in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -193,33 +234,141 @@
outputFileListPaths = ( outputFileListPaths = (
); );
outputPaths = ( outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-HIPMIBADUNG-checkManifestLockResult.txt", "$(DERIVED_FILE_DIR)/Pods-HIPMIBadungConnect-checkManifestLockResult.txt",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
0B90913696EEE0E819CAF510 /* [Expo] Configure project */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"$(SRCROOT)/.xcode.env",
"$(SRCROOT)/.xcode.env.local",
"$(SRCROOT)/HIPMIBadungConnect/HIPMIBadungConnect.entitlements",
"$(SRCROOT)/Pods/Target Support Files/Pods-HIPMIBadungConnect/expo-configure-project.sh",
);
name = "[Expo] Configure project";
outputFileListPaths = (
);
outputPaths = (
"$(SRCROOT)/Pods/Target Support Files/Pods-HIPMIBadungConnect/ExpoModulesProvider.swift",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-HIPMIBadungConnect/expo-configure-project.sh\"\n";
};
2DA25245F64078F29C0B38E4 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-HIPMIBadungConnect/Pods-HIPMIBadungConnect-frameworks.sh",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/React-Core-prebuilt/React.framework/React",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/ReactNativeDependencies/ReactNativeDependencies.framework/ReactNativeDependencies",
"${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactNativeDependencies.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HIPMIBadungConnect/Pods-HIPMIBadungConnect-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */ = { 800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputPaths = ( inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-HIPMIBADUNG/Pods-HIPMIBADUNG-resources.sh", "${PODS_ROOT}/Target Support Files/Pods-HIPMIBadungConnect/Pods-HIPMIBadungConnect-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/EXApplication/ExpoApplication_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/EXUpdates/EXUpdates.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/ExpoConstants_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/RCTI18nStrings.bundle", "${PODS_CONFIGURATION_BUILD_DIR}/EXNotifications/ExpoNotifications_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoDevice/ExpoDevice_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoFileSystem/ExpoFileSystem_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/ExpoSystemUI/ExpoSystemUI_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNCAsyncStorage/RNCAsyncStorage_resources.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome6_Brands.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome6_Regular.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome6_Solid.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Fontisto.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Foundation.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-launcher/EXDevLauncher.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-menu/EXDevMenu.bundle",
"${PODS_CONFIGURATION_BUILD_DIR}/react-native-maps/ReactNativeMapsPrivacy.bundle",
); );
name = "[CP] Copy Pods Resources"; name = "[CP] Copy Pods Resources";
outputPaths = ( outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoApplication_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXUpdates.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoConstants_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCTI18nStrings.bundle", "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoNotifications_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoDevice_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoFileSystem_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ExpoSystemUI_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNCAsyncStorage_resources.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EvilIcons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Feather.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Brands.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Regular.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Solid.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome6_Brands.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome6_Regular.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome6_Solid.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Fontisto.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Foundation.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Ionicons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialCommunityIcons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialIcons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SDWebImage.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevLauncher.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevMenu.bundle",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ReactNativeMapsPrivacy.bundle",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HIPMIBADUNG/Pods-HIPMIBADUNG-resources.sh\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HIPMIBadungConnect/Pods-HIPMIBadungConnect-resources.sh\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
/* End PBXShellScriptBuildPhase section */ /* End PBXShellScriptBuildPhase section */
@@ -230,6 +379,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
F11748422D0307B40044C1D9 /* AppDelegate.swift in Sources */, F11748422D0307B40044C1D9 /* AppDelegate.swift in Sources */,
D138B3E4BC618ADDE62DCDCC /* ExpoModulesProvider.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -238,16 +388,19 @@
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = { 13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 1E94102500A8768C71C74AF6 /* Pods-HIPMIBadungConnect.debug.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1; CODE_SIGN_ENTITLEMENTS = HIPMIBadungConnect/HIPMIBadungConnect.entitlements;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = BMY6GT6W3D;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
GCC_PREPROCESSOR_DEFINITIONS = ( GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)", "$(inherited)",
"FB_SONARKIT_ENABLED=1", "FB_SONARKIT_ENABLED=1",
); );
INFOPLIST_FILE = HIPMIBADUNG/Info.plist; INFOPLIST_FILE = HIPMIBadungConnect/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.1; IPHONEOS_DEPLOYMENT_TARGET = 15.1;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -259,24 +412,27 @@
"-ObjC", "-ObjC",
"-lc++", "-lc++",
); );
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
PRODUCT_BUNDLE_IDENTIFIER = "com.anonymous.hipmi-mobile"; PRODUCT_BUNDLE_IDENTIFIER = "com.anonymous.hipmi-mobile";
PRODUCT_NAME = "HIPMIBADUNG"; PRODUCT_NAME = "HIPMIBadungConnect";
SWIFT_OBJC_BRIDGING_HEADER = "HIPMIBADUNG/HIPMIBADUNG-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "HIPMIBadungConnect/HIPMIBadungConnect-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
CODE_SIGN_ENTITLEMENTS = HIPMIBADUNG/HIPMIBADUNG.entitlements; VERSIONING_SYSTEM = "apple-generic";
}; };
name = Debug; name = Debug;
}; };
13B07F951A680F5B00A75B9A /* Release */ = { 13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = C19B4954908DD0D4CD2965DF /* Pods-HIPMIBadungConnect.release.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1; CODE_SIGN_ENTITLEMENTS = HIPMIBadungConnect/HIPMIBadungConnect.entitlements;
INFOPLIST_FILE = HIPMIBADUNG/Info.plist; CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = BMY6GT6W3D;
INFOPLIST_FILE = HIPMIBadungConnect/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.1; IPHONEOS_DEPLOYMENT_TARGET = 15.1;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@@ -288,13 +444,13 @@
"-ObjC", "-ObjC",
"-lc++", "-lc++",
); );
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
PRODUCT_BUNDLE_IDENTIFIER = "com.anonymous.hipmi-mobile"; PRODUCT_BUNDLE_IDENTIFIER = "com.anonymous.hipmi-mobile";
PRODUCT_NAME = "HIPMIBADUNG"; PRODUCT_NAME = "HIPMIBadungConnect";
SWIFT_OBJC_BRIDGING_HEADER = "HIPMIBADUNG/HIPMIBADUNG-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "HIPMIBadungConnect/HIPMIBadungConnect-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
CODE_SIGN_ENTITLEMENTS = HIPMIBADUNG/HIPMIBADUNG.entitlements; VERSIONING_SYSTEM = "apple-generic";
}; };
name = Release; name = Release;
}; };
@@ -350,10 +506,14 @@
/usr/lib/swift, /usr/lib/swift,
"$(inherited)", "$(inherited)",
); );
LIBRARY_SEARCH_PATHS = "\"$(inherited)\""; LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
SWIFT_ENABLE_EXPLICIT_MODULES = NO;
USE_HERMES = true;
}; };
name = Debug; name = Debug;
}; };
@@ -402,9 +562,12 @@
/usr/lib/swift, /usr/lib/swift,
"$(inherited)", "$(inherited)",
); );
LIBRARY_SEARCH_PATHS = "\"$(inherited)\""; LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos; SDKROOT = iphoneos;
SWIFT_ENABLE_EXPLICIT_MODULES = NO;
USE_HERMES = true;
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };
name = Release; name = Release;
@@ -412,7 +575,7 @@
/* End XCBuildConfiguration section */ /* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */ /* Begin XCConfigurationList section */
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "HIPMIBADUNG" */ = { 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "HIPMIBadungConnect" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
13B07F941A680F5B00A75B9A /* Debug */, 13B07F941A680F5B00A75B9A /* Debug */,
@@ -421,7 +584,7 @@
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "HIPMIBADUNG" */ = { 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "HIPMIBadungConnect" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
83CBBA201A601CBA00E9B192 /* Debug */, 83CBBA201A601CBA00E9B192 /* Debug */,

View File

@@ -15,9 +15,9 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A" BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "HIPMIBADUNG.app" BuildableName = "HIPMIBadungConnect.app"
BlueprintName = "HIPMIBADUNG" BlueprintName = "HIPMIBadungConnect"
ReferencedContainer = "container:HIPMIBADUNG.xcodeproj"> ReferencedContainer = "container:HIPMIBadungConnect.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildActionEntry> </BuildActionEntry>
</BuildActionEntries> </BuildActionEntries>
@@ -33,9 +33,9 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "00E356ED1AD99517003FC87E" BlueprintIdentifier = "00E356ED1AD99517003FC87E"
BuildableName = "HIPMIBADUNGTests.xctest" BuildableName = "HIPMIBadungConnectTests.xctest"
BlueprintName = "HIPMIBADUNGTests" BlueprintName = "HIPMIBadungConnectTests"
ReferencedContainer = "container:HIPMIBADUNG.xcodeproj"> ReferencedContainer = "container:HIPMIBadungConnect.xcodeproj">
</BuildableReference> </BuildableReference>
</TestableReference> </TestableReference>
</Testables> </Testables>
@@ -55,9 +55,9 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A" BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "HIPMIBADUNG.app" BuildableName = "HIPMIBadungConnect.app"
BlueprintName = "HIPMIBADUNG" BlueprintName = "HIPMIBadungConnect"
ReferencedContainer = "container:HIPMIBADUNG.xcodeproj"> ReferencedContainer = "container:HIPMIBadungConnect.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildableProductRunnable> </BuildableProductRunnable>
</LaunchAction> </LaunchAction>
@@ -72,9 +72,9 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A" BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "HIPMIBADUNG.app" BuildableName = "HIPMIBadungConnect.app"
BlueprintName = "HIPMIBADUNG" BlueprintName = "HIPMIBadungConnect"
ReferencedContainer = "container:HIPMIBADUNG.xcodeproj"> ReferencedContainer = "container:HIPMIBadungConnect.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildableProductRunnable> </BuildableProductRunnable>
</ProfileAction> </ProfileAction>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:HIPMIBadungConnect.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:cld-dkr-staging-hipmi.wibudev.com</string>
</array>
</dict>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

View File

@@ -7,7 +7,7 @@
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>HIPMI BADUNG</string> <string>HIPMI Badung Connect</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@@ -19,7 +19,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.0.0</string> <string>1.0.1</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleURLTypes</key> <key>CFBundleURLTypes</key>
@@ -39,7 +39,7 @@
</dict> </dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1</string> <string>7</string>
<key>ITSAppUsesNonExemptEncryption</key> <key>ITSAppUsesNonExemptEncryption</key>
<false/> <false/>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
@@ -63,6 +63,8 @@
<array> <array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>
</array> </array>
<key>RCTNewArchEnabled</key>
<true/>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>SplashScreen</string> <string>SplashScreen</string>
<key>UIRequiredDeviceCapabilities</key> <key>UIRequiredDeviceCapabilities</key>

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
<string>0A2A.1</string>
<string>3B52.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>E174.1</string>
<string>85F4.1</string>
</array>
</dict>
</array>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyTracking</key>
<false/>
</dict>
</plist>

View File

@@ -12,7 +12,7 @@ platform :ios, podfile_properties['ios.deploymentTarget'] || '15.1'
prepare_react_native_project! prepare_react_native_project!
target 'HIPMIBADUNG' do target 'HIPMIBadungConnect' do
use_expo_modules! use_expo_modules!
if ENV['EXPO_USE_COMMUNITY_AUTOLINKING'] == '1' if ENV['EXPO_USE_COMMUNITY_AUTOLINKING'] == '1'

2899
ios/Podfile.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -36,7 +36,7 @@ const listDataNotPublishInvesment = ({ data }: { data: any }) => [
const listDataPublishInvesment = ({ data }: { data: any }) => [ const listDataPublishInvesment = ({ data }: { data: any }) => [
{ {
label: "Investor", label: "Investor",
value: data?.investor, value: data?.Investasi_Invoice.length || "-",
}, },
{ {
label: "Target Dana", label: "Target Dana",

View File

@@ -1,7 +1,7 @@
{ {
"name": "hipmi-mobile", "name": "hipmi-mobile",
"main": "expo-router/entry", "main": "expo-router/entry",
"version": "1.0.0", "version": "1.0.1",
"scripts": { "scripts": {
"start": "bunx expo start", "start": "bunx expo start",
"reset-project": "node ./scripts/reset-project.js", "reset-project": "node ./scripts/reset-project.js",
@@ -26,8 +26,9 @@
"expo": "^54.0.0", "expo": "^54.0.0",
"expo-camera": "~17.0.7", "expo-camera": "~17.0.7",
"expo-clipboard": "~8.0.7", "expo-clipboard": "~8.0.7",
"expo-constants": "~18.0.8", "expo-constants": "^18.0.10",
"expo-dev-client": "~6.0.12", "expo-dev-client": "~6.0.12",
"expo-device": "^8.0.9",
"expo-document-picker": "~14.0.7", "expo-document-picker": "~14.0.7",
"expo-file-system": "^19.0.15", "expo-file-system": "^19.0.15",
"expo-font": "~14.0.8", "expo-font": "~14.0.8",
@@ -35,12 +36,13 @@
"expo-image": "~3.0.8", "expo-image": "~3.0.8",
"expo-image-picker": "~17.0.8", "expo-image-picker": "~17.0.8",
"expo-linking": "~8.0.8", "expo-linking": "~8.0.8",
"expo-notifications": "^0.32.13",
"expo-router": "~6.0.1", "expo-router": "~6.0.1",
"expo-splash-screen": "~31.0.9", "expo-splash-screen": "~31.0.9",
"expo-status-bar": "~3.0.8", "expo-status-bar": "~3.0.8",
"expo-symbols": "~1.0.7", "expo-symbols": "~1.0.7",
"expo-system-ui": "~6.0.7", "expo-system-ui": "~6.0.7",
"expo-web-browser": "~15.0.7", "expo-web-browser": "~15.0.9",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"react": "19.1.0", "react": "19.1.0",
"react-dom": "19.1.0", "react-dom": "19.1.0",

View File

@@ -0,0 +1,164 @@
import Spacing from "@/components/_ShareComponent/Spacing";
import ViewWrapper from "@/components/_ShareComponent/ViewWrapper";
import ButtonCustom from "@/components/Button/ButtonCustom";
import { MainColor } from "@/constants/color-palet";
import { useAuth } from "@/hooks/use-auth";
import { apiCheckCodeOtp } from "@/service/api-config";
import { GStyles } from "@/styles/global-styles";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { router, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import { Text, View } from "react-native";
import { OtpInput } from "react-native-otp-entry";
import { ActivityIndicator } from "react-native-paper";
import Toast from "react-native-toast-message";
export default function VerificationView() {
const { nomor } = useLocalSearchParams();
const [codeOtp, setCodeOtp] = useState<string>("");
const [inputOtp, setInputOtp] = useState<string>("");
const [userNumber, setUserNumber] = useState<string>("");
const [loading, setLoading] = useState<boolean>(false);
const [recodeOtp, setRecodeOtp] = useState<boolean>(false);
// --- Context ---
const { validateOtp, isLoading, loginWithNomor } = useAuth();
useEffect(() => {
onLoadCheckCodeOtp();
}, [recodeOtp]);
async function onLoadCheckCodeOtp() {
setRecodeOtp(false);
const kodeId = await AsyncStorage.getItem("kode_otp");
const response = await apiCheckCodeOtp({ kodeId: kodeId as string });
console.log(
"Response check code otp >>",
JSON.stringify(response.otp, null, 2)
);
setCodeOtp(response.otp);
setUserNumber(response.nomor);
}
const handlerResendOtp = async () => {
try {
setLoading(true);
await loginWithNomor(nomor as string);
setRecodeOtp(true);
} catch (error) {
console.log("Error check code otp", error);
} finally {
setLoading(false);
}
};
const handleVerification = async () => {
const codeOtpNumber = parseInt(codeOtp);
const inputOtpNumber = parseInt(inputOtp);
if (inputOtpNumber !== codeOtpNumber) {
Toast.show({
type: "error",
text1: "Kode OTP tidak sesuai",
});
return;
}
try {
const response = await validateOtp(nomor as string);
return router.replace(response);
// if (response.success) {
// await userData(response.token);
// if (response.active) {
// if (response.roleId === "1") {
// return "/(application)/(user)/home";
// } else {
// return "/(application)/admin/dashboard";
// }
// } else {
// return "/(application)/(user)/waiting-room";
// }
// } else {
// Toast.show({
// type: "info",
// text1: "Anda belum terdaftar",
// text2: "Silahkan daftar terlebih dahulu",
// });
// return `/register?nomor=${nomor}`;
// }
} catch (error) {
console.log("Error verification", error);
}
};
return (
<>
<ViewWrapper withBackground>
<View style={GStyles.authContainer}>
<View>
<View style={GStyles.authContainerTitle}>
<Text style={GStyles.authTitle}>Verifikasi Kode OTP</Text>
<Spacing height={30} />
<Text style={GStyles.textLabel}>Masukan 4 digit kode otp</Text>
<Text style={GStyles.textLabel}>
Yang di kirim ke +{userNumber}
</Text>
<Spacing height={30} />
<OtpInput
disabled={codeOtp === ""}
numberOfDigits={4}
theme={{
pinCodeContainerStyle: {
backgroundColor: MainColor.text_input,
borderRadius: 10,
borderWidth: 1,
borderColor: MainColor.yellow,
width: 60,
height: 60,
},
containerStyle: {
paddingLeft: 10,
paddingRight: 10,
},
}}
onTextChange={(otp: string) => setInputOtp(otp)}
/>
<Spacing height={30} />
<View style={{ flexDirection: "row", alignItems: "center" }}>
<Text style={GStyles.textLabel}>Tidak menerima kode ? </Text>
{loading ? (
<ActivityIndicator size={10} color={MainColor.yellow} />
) : (
<Text
style={GStyles.textLabel}
onPress={() => {
handlerResendOtp();
}}
>
Kirim Ulang
</Text>
)}
</View>
</View>
<Spacing height={30} />
</View>
<ButtonCustom
isLoading={isLoading}
disabled={codeOtp === "" || recodeOtp === true}
backgroundColor={MainColor.yellow}
textColor={MainColor.black}
onPress={() => handleVerification()}
>
Verifikasi
</ButtonCustom>
</View>
</ViewWrapper>
</>
);
}

View File

@@ -5,74 +5,117 @@ import { MainColor } from "@/constants/color-palet";
import { useAuth } from "@/hooks/use-auth"; import { useAuth } from "@/hooks/use-auth";
import { apiCheckCodeOtp } from "@/service/api-config"; import { apiCheckCodeOtp } from "@/service/api-config";
import { GStyles } from "@/styles/global-styles"; import { GStyles } from "@/styles/global-styles";
import { registerForPushNotificationsAsync } from "@/utils/notifications";
import AsyncStorage from "@react-native-async-storage/async-storage"; import AsyncStorage from "@react-native-async-storage/async-storage";
import { router, useLocalSearchParams } from "expo-router"; import { router, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Text, View } from "react-native"; import { Text, View } from "react-native";
import { OtpInput } from "react-native-otp-entry"; import { OtpInput } from "react-native-otp-entry";
import { ActivityIndicator } from "react-native-paper";
import Toast from "react-native-toast-message"; import Toast from "react-native-toast-message";
export default function VerificationView() { export default function VerificationView() {
const { nomor } = useLocalSearchParams(); const { nomor } = useLocalSearchParams<{ nomor: string }>();
const [codeOtp, setCodeOtp] = useState<string>("");
const [inputOtp, setInputOtp] = useState<string>(""); const [inputOtp, setInputOtp] = useState<string>("");
const [userNumber, setUserNumber] = useState<string>(""); const [userNumber, setUserNumber] = useState<string>("");
const [loading, setLoading] = useState<boolean>(false);
const [recodeOtp, setRecodeOtp] = useState<boolean>(false);
// 🔑 DETEKSI MODE REVIEW (HANYA UNTUK NOMOR DEMO & PRODUCTION)
const isReviewMode =
typeof window !== "undefined" && // pastikan di browser/production
process.env.NODE_ENV === "production" &&
nomor === "6282340374412";
// --- Context --- // --- Context ---
const { validateOtp, isLoading } = useAuth(); const { validateOtp, isLoading, loginWithNomor } = useAuth();
useEffect(() => { useEffect(() => {
onLoadCheckCodeOtp(); setUserNumber(nomor?.replace(/^\+/, "") || "");
}, []);
async function onLoadCheckCodeOtp() { if (!isReviewMode) {
const kodeId = await AsyncStorage.getItem("kode_otp"); // Hanya jalankan logika OTP normal jika BUKAN review mode
const response = await apiCheckCodeOtp({ kodeId: kodeId as string }); onLoadCheckCodeOtp();
console.log("Response check code otp >>", JSON.stringify(response.otp, null, 2));
setCodeOtp(response.otp);
setUserNumber(response.nomor);
} }
const handleVerification = async () => { console.log("[NODE_ENV]:", process.env.NODE_ENV);
const codeOtpNumber = parseInt(codeOtp); console.log("[isReviewMode]:", isReviewMode);
const inputOtpNumber = parseInt(inputOtp); console.log("[nomor]:", nomor);
}, [recodeOtp, isReviewMode]);
if (inputOtpNumber !== codeOtpNumber) { async function onLoadCheckCodeOtp() {
Toast.show({ setRecodeOtp(false);
type: "error", const kodeId = await AsyncStorage.getItem("kode_otp");
text1: "Kode OTP tidak sesuai", if (!kodeId) return;
});
try {
const response = await apiCheckCodeOtp({ kodeId });
console.log(
"Response check code otp >>",
JSON.stringify(response.otp, null, 2)
);
// Kita tidak perlu simpan codeOtp di state karena verifikasi dilakukan di backend
// Cukup simpan nomor
} catch (error) {
console.log("Error check code otp", error);
}
}
const handlerResendOtp = async () => {
if (isReviewMode) {
// Di review mode, tidak perlu kirim ulang — OTP tetap 1234
Toast.show({ type: "info", text1: "OTP demo: 1234" });
return; return;
} }
try {
setLoading(true);
await loginWithNomor(nomor as string);
setRecodeOtp(true);
// ❌ Kamu tidak punya nomor di sini, jadi pastikan `nomor` tersedia
// Sebaiknya simpan nomor saat login, atau gunakan dari `useLocalSearchParams`
router.setParams({ nomor }); // opsional
} catch (error) {
console.log("Error resend OTP", error);
} finally {
setLoading(false);
}
};
const handleVerification = async () => {
if (isReviewMode) {
// ✅ VERIFIKASI OTOMATIS UNTUK APPLE REVIEW
if (inputOtp === "1234") {
try { try {
const response = await validateOtp(nomor as string); const response = await validateOtp(nomor as string);
return router.replace(response); router.replace(response);
// if (response.success) {
// await userData(response.token);
// if (response.active) {
// if (response.roleId === "1") {
// return "/(application)/(user)/home";
// } else {
// return "/(application)/admin/dashboard";
// }
// } else {
// return "/(application)/(user)/waiting-room";
// }
// } else {
// Toast.show({
// type: "info",
// text1: "Anda belum terdaftar",
// text2: "Silahkan daftar terlebih dahulu",
// });
// return `/register?nomor=${nomor}`;
// }
} catch (error) { } catch (error) {
console.log("Error verification", error); console.log("Error verification", error);
Toast.show({ type: "error", text1: "Gagal verifikasi" });
}
} else {
Toast.show({ type: "error", text1: "Kode OTP tidak sesuai" });
}
return;
}
// 🔁 VERIFIKASI NORMAL (untuk pengguna sungguhan)
try {
const response = await validateOtp(nomor as string);
// registerForPushNotificationsAsync().then((token) => {
// if (token) {
// console.log("Expo Push Token:", token);
// // TODO: Kirim token ke backend kamu
// } else {
// console.log("Failed to get Expo Push Token");
// }
// });
router.replace(response);
} catch (error) {
console.log("Error verification", error);
Toast.show({ type: "error", text1: "Gagal verifikasi" });
} }
}; };
@@ -90,7 +133,7 @@ export default function VerificationView() {
</Text> </Text>
<Spacing height={30} /> <Spacing height={30} />
<OtpInput <OtpInput
disabled={codeOtp === ""} disabled={isReviewMode ? false : false} // tetap aktif
numberOfDigits={4} numberOfDigits={4}
theme={{ theme={{
pinCodeContainerStyle: { pinCodeContainerStyle: {
@@ -109,20 +152,26 @@ export default function VerificationView() {
onTextChange={(otp: string) => setInputOtp(otp)} onTextChange={(otp: string) => setInputOtp(otp)}
/> />
<Spacing height={30} /> <Spacing height={30} />
<Text style={GStyles.textLabel}> <View style={{ flexDirection: "row", alignItems: "center" }}>
Tidak menerima kode ?{" "} <Text style={GStyles.textLabel}>Tidak menerima kode?</Text>
<Text style={GStyles.textLabel}>Kirim Ulang</Text> {loading ? (
<ActivityIndicator size={10} color={MainColor.yellow} />
) : (
<Text style={GStyles.textLabel} onPress={handlerResendOtp}>
{" Kirim Ulang"}
</Text> </Text>
)}
</View>
</View> </View>
<Spacing height={30} /> <Spacing height={30} />
</View> </View>
<ButtonCustom <ButtonCustom
isLoading={isLoading} isLoading={isLoading}
disabled={codeOtp === ""} disabled={inputOtp.length < 4}
backgroundColor={MainColor.yellow} backgroundColor={MainColor.yellow}
textColor={MainColor.black} textColor={MainColor.black}
onPress={() => handleVerification()} onPress={handleVerification}
> >
Verifikasi Verifikasi
</ButtonCustom> </ButtonCustom>

View File

@@ -1,12 +1,35 @@
import { ClickableCustom, TextCustom } from "@/components"; import { ClickableCustom, TextCustom } from "@/components";
import Spacing from "@/components/_ShareComponent/Spacing"; import Spacing from "@/components/_ShareComponent/Spacing";
import React from "react"; import React, { useCallback, useState } from "react";
import { View } from "react-native"; import { View } from "react-native";
import Icon from "react-native-vector-icons/FontAwesome"; import Icon from "react-native-vector-icons/FontAwesome";
import { stylesHome } from "./homeViewStyle"; import { stylesHome } from "./homeViewStyle";
import { router } from "expo-router"; import { router, useFocusEffect } from "expo-router";
import { apiJobGetAll } from "@/service/api-client/api-job";
export default function Home_BottomFeatureSection() { export default function Home_BottomFeatureSection() {
const [listData, setListData] = useState<any>([]);
const onLoadData = async () => {
try {
const response = await apiJobGetAll({
category: "beranda",
});
// console.log("[DATA JOB]", JSON.stringify(response.data, null, 2));
const result = response.data.slice(-2);
setListData(result);
} catch (error) {
console.log("[ERROR]", error);
}
};
useFocusEffect(
useCallback(() => {
onLoadData();
}, [])
);
return ( return (
<> <>
<ClickableCustom onPress={() => router.push("/job")}> <ClickableCustom onPress={() => router.push("/job")}>
@@ -21,32 +44,17 @@ export default function Home_BottomFeatureSection() {
<View style={stylesHome.vacancyList}> <View style={stylesHome.vacancyList}>
{/* Vacancy Item 1 */} {/* Vacancy Item 1 */}
<View style={stylesHome.vacancyItem}> {listData.map((item: any, index: number) => (
{/* <Icon name="user" size={20} color="#FFD700" /> */} <View style={stylesHome.vacancyItem} key={index}>
<View style={stylesHome.vacancyDetails}> <View style={stylesHome.vacancyDetails}>
<TextCustom bold color="yellow" truncate size="large"> <TextCustom bold color="yellow" truncate size="large">
Bagas_banuna {item.title}
</TextCustom> </TextCustom>
<Spacing height={5} /> <Spacing height={5} />
<TextCustom truncate={2}> <TextCustom truncate={2}>{item.deskripsi}</TextCustom>
Dicari perawat kucing dan perawat anjing
</TextCustom>
</View>
</View>
{/* Vacancy Item 2 */}
<View style={stylesHome.vacancyItem}>
{/* <Icon name="user" size={20} color="#FFD700" /> */}
<View style={stylesHome.vacancyDetails}>
<TextCustom bold color="yellow" truncate size="large">
fibramarcell
</TextCustom>
<Spacing height={5} />
<TextCustom truncate={2}>
Di Butuhkan Seorang Programer dan Designer
</TextCustom>
</View> </View>
</View> </View>
))}
</View> </View>
</View> </View>
</ClickableCustom> </ClickableCustom>

View File

@@ -0,0 +1,96 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
BaseBox,
Grid,
ProgressCustom,
StackCustom,
TextCustom,
} from "@/components";
import API_STRORAGE from "@/constants/base-url-api-strorage";
import DUMMY_IMAGE from "@/constants/dummy-image-value";
import { countDownAndCondition } from "@/utils/countDownAndCondition";
import { Ionicons } from "@expo/vector-icons";
import { Image } from "expo-image";
import { useEffect, useState } from "react";
import { View } from "react-native";
export default function Investment_BoxBerandaSection({
id,
data,
}: {
id: string;
data: any;
}) {
// console.log("[DATA By one]", JSON.stringify(data, null, 2));
const [value, setValue] = useState({
sisa: 0,
reminder: false,
});
useEffect(() => {
updateCountDown();
}, [data]);
const updateCountDown = () => {
const countDown = countDownAndCondition({
duration: data?.pencarianInvestor,
publishTime: data?.countDown,
});
setValue({
sisa: countDown.durationDay,
reminder: countDown.reminder,
});
};
return (
<>
<BaseBox paddingTop={7} paddingBottom={7} href={`/investment/${id}`}>
<Grid>
<Grid.Col span={5}>
<Image
source={
data && data.imageId
? API_STRORAGE.GET({ fileId: data.imageId })
: DUMMY_IMAGE.background
}
style={{ width: "auto", height: 100, borderRadius: 10 }}
/>
</Grid.Col>
<Grid.Col span={1}>
<View />
</Grid.Col>
<Grid.Col span={6}>
<StackCustom>
<TextCustom truncate={2}>{data.title}</TextCustom>
<ProgressCustom
label={`${data.progress}%`}
value={data.progress}
size="lg"
/>
{value.reminder ? (
<View
style={{
flexDirection: "row",
alignItems: "center",
gap: 5,
}}
>
<Ionicons name="alert-circle-outline" size={16} color="red" />
<TextCustom truncate color="red" size="small">
Periode Investasi Berakhir
</TextCustom>
</View>
) : (
<TextCustom>
Sisa waktu: {value.sisa} hari
</TextCustom>
)}
</StackCustom>
</Grid.Col>
</Grid>
</BaseBox>
</>
);
}

View File

@@ -7,7 +7,7 @@ export default function Invesment_BoxProgressSection({progress, status}: {progre
<BaseBox> <BaseBox>
<StackCustom> <StackCustom>
<TextCustom bold>Progress Saham</TextCustom> <TextCustom bold>Progress Saham</TextCustom>
<ProgressCustom label={progress + "%"} value={progress} size="lg" /> <ProgressCustom label={(progress || 0) + "%"} value={progress || 0} size="lg" />
</StackCustom> </StackCustom>
</BaseBox> </BaseBox>
)} )}

View File

@@ -1,9 +1,12 @@
import { Spacing, StackCustom } from "@/components"; /* eslint-disable react-hooks/exhaustive-deps */
import { ButtonCustom, Spacing, StackCustom } from "@/components";
import ReportBox from "@/components/Box/ReportBox";
import { import {
listDataNotPublishInvesment, listDataNotPublishInvesment,
listDataPublishInvesment, listDataPublishInvesment,
} from "@/lib/dummy-data/investment/dummy-data-not-publish"; } from "@/lib/dummy-data/investment/dummy-data-not-publish";
import React from "react"; import { countDownAndCondition } from "@/utils/countDownAndCondition";
import React, { useEffect, useState } from "react";
import Invesment_BoxDetailDataSection from "./BoxDetailDataSection"; import Invesment_BoxDetailDataSection from "./BoxDetailDataSection";
import Invesment_BoxProgressSection from "./BoxProgressSection"; import Invesment_BoxProgressSection from "./BoxProgressSection";
import Investment_ButtonStatusSection from "./ButtonStatusSection"; import Investment_ButtonStatusSection from "./ButtonStatusSection";
@@ -19,11 +22,39 @@ export default function Invesment_DetailDataPublishSection({
bottomSection?: React.ReactNode; bottomSection?: React.ReactNode;
buttonSection?: React.ReactNode; buttonSection?: React.ReactNode;
}) { }) {
const [value, setValue] = useState({
sisa: 0,
reminder: false,
});
useEffect(() => {
updateCountDown();
}, [data]);
const updateCountDown = () => {
const countDown = countDownAndCondition({
duration: data?.durasiDonasi,
publishTime: data?.publishTime,
});
setValue({
sisa: countDown.durationDay,
reminder: countDown.reminder,
});
};
return ( return (
<> <>
<StackCustom gap={"sm"}> <StackCustom gap={"sm"}>
<Invesment_BoxProgressSection progress={data?.progress} status={status as string} /> {data &&
data?.catatan &&
(status === "draft" || status === "reject") && (
<ReportBox text={data?.catatan} />
)}
<Invesment_BoxProgressSection
progress={data?.progress}
status={status as string}
/>
<Invesment_BoxDetailDataSection <Invesment_BoxDetailDataSection
title={data?.title} title={data?.title}
author={data?.author} author={data?.author}
@@ -35,11 +66,18 @@ export default function Invesment_DetailDataPublishSection({
} }
bottomSection={bottomSection} bottomSection={bottomSection}
/> />
{value.reminder ? (
<ButtonCustom disabled>
Periode Investasi Berakhir
</ButtonCustom>
) : (
<Investment_ButtonStatusSection <Investment_ButtonStatusSection
id={data?.id} id={data?.id}
status={status as string} status={status as string}
buttonPublish={buttonSection} buttonPublish={buttonSection}
/> />
)}
</StackCustom> </StackCustom>
<Spacing /> <Spacing />
</> </>

View File

@@ -1,6 +1,7 @@
import { IMenuDrawerItem } from "@/components/_Interface/types"; import { IMenuDrawerItem } from "@/components/_Interface/types";
import { AccentColor, MainColor } from "@/constants/color-palet"; import { AccentColor, MainColor } from "@/constants/color-palet";
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value"; import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
import { useAuth } from "@/hooks/use-auth";
import { Ionicons } from "@expo/vector-icons"; import { Ionicons } from "@expo/vector-icons";
export const drawerItemsProfile = ({ export const drawerItemsProfile = ({
@@ -10,6 +11,8 @@ export const drawerItemsProfile = ({
id: string; id: string;
isAdmin: boolean; isAdmin: boolean;
}) => { }) => {
const { user } = useAuth();
const adminItems: IMenuDrawerItem[] = [ const adminItems: IMenuDrawerItem[] = [
{ {
icon: ( icon: (
@@ -21,6 +24,7 @@ export const drawerItemsProfile = ({
), ),
label: "Edit profile", label: "Edit profile",
path: `/(application)/profile/${id}/edit`, path: `/(application)/profile/${id}/edit`,
value: "edit-profile",
}, },
{ {
icon: ( icon: (
@@ -32,6 +36,7 @@ export const drawerItemsProfile = ({
), ),
label: "Ubah foto profile", label: "Ubah foto profile",
path: `/(application)/profile/${id}/update-photo`, path: `/(application)/profile/${id}/update-photo`,
value: "update-photo",
}, },
{ {
icon: ( icon: (
@@ -43,6 +48,7 @@ export const drawerItemsProfile = ({
), ),
label: "Ubah latar belakang", label: "Ubah latar belakang",
path: `/(application)/profile/${id}/update-background`, path: `/(application)/profile/${id}/update-background`,
value: "update-background",
}, },
{ {
icon: ( icon: (
@@ -54,6 +60,7 @@ export const drawerItemsProfile = ({
), ),
label: "Tambah portofolio", label: "Tambah portofolio",
path: `/(application)/portofolio/${id}/create`, path: `/(application)/portofolio/${id}/create`,
value: "create-portofolio",
}, },
{ {
icon: ( icon: (
@@ -65,6 +72,20 @@ export const drawerItemsProfile = ({
), ),
label: "Dashboard Admin", label: "Dashboard Admin",
path: `/(application)/admin/dashboard`, path: `/(application)/admin/dashboard`,
value: "dashboard-admin",
},
{
icon: (
<Ionicons
name="trash"
size={ICON_SIZE_MEDIUM}
color={AccentColor.white}
/>
),
label: "Hapus Akun",
color: MainColor.red,
path: `/(application)/(user)/delete-account?phone=${user?.nomor}`,
value: "delete-account",
}, },
{ {
icon: ( icon: (
@@ -77,6 +98,7 @@ export const drawerItemsProfile = ({
label: "Keluar", label: "Keluar",
color: MainColor.red, color: MainColor.red,
path: "", path: "",
value: "logout",
}, },
]; ];
@@ -91,6 +113,7 @@ export const drawerItemsProfile = ({
), ),
label: "Edit profile", label: "Edit profile",
path: `/(application)/profile/${id}/edit`, path: `/(application)/profile/${id}/edit`,
value: "edit-profile",
}, },
{ {
icon: ( icon: (
@@ -102,6 +125,7 @@ export const drawerItemsProfile = ({
), ),
label: "Ubah foto profile", label: "Ubah foto profile",
path: `/(application)/profile/${id}/update-photo`, path: `/(application)/profile/${id}/update-photo`,
value: "update-photo",
}, },
{ {
icon: ( icon: (
@@ -113,6 +137,7 @@ export const drawerItemsProfile = ({
), ),
label: "Ubah latar belakang", label: "Ubah latar belakang",
path: `/(application)/profile/${id}/update-background`, path: `/(application)/profile/${id}/update-background`,
value: "update-background",
}, },
{ {
icon: ( icon: (
@@ -124,6 +149,20 @@ export const drawerItemsProfile = ({
), ),
label: "Tambah portofolio", label: "Tambah portofolio",
path: `/(application)/portofolio/${id}/create`, path: `/(application)/portofolio/${id}/create`,
value: "create-portofolio",
},
{
icon: (
<Ionicons
name="trash"
size={ICON_SIZE_MEDIUM}
color={AccentColor.white}
/>
),
label: "Hapus Akun",
color: MainColor.red,
path: `/(application)/(user)/delete-account?phone=${user?.nomor}`,
value: "delete-account",
}, },
{ {
icon: ( icon: (
@@ -136,6 +175,7 @@ export const drawerItemsProfile = ({
label: "Keluar", label: "Keluar",
color: MainColor.red, color: MainColor.red,
path: "", path: "",
value: "logout",
}, },
]; ];

View File

@@ -1,6 +1,9 @@
import { AlertDefaultSystem } from "@/components"; import { AlertDefaultSystem } from "@/components";
import { IMenuDrawerItem } from "@/components/_Interface/types"; import { IMenuDrawerItem } from "@/components/_Interface/types";
import MenuDrawerDynamicGrid from "@/components/Drawer/MenuDrawerDynamicGird"; import MenuDrawerDynamicGrid from "@/components/Drawer/MenuDrawerDynamicGird";
import { useAuth } from "@/hooks/use-auth";
import { apiDeleteUser } from "@/service/api-client/api-user";
import { openBrowser } from "@/utils/openBrower";
import { router } from "expo-router"; import { router } from "expo-router";
export default function Profile_MenuDrawerSection({ export default function Profile_MenuDrawerSection({
@@ -12,8 +15,11 @@ export default function Profile_MenuDrawerSection({
setIsDrawerOpen: (value: boolean) => void; setIsDrawerOpen: (value: boolean) => void;
logout: () => Promise<void>; logout: () => Promise<void>;
}) { }) {
const { user } = useAuth();
const handlePress = (item: IMenuDrawerItem) => { const handlePress = (item: IMenuDrawerItem) => {
if (item.label === "Keluar") { // console.log("ITEM >> ", item);
if (item.value === "logout") {
// console.log("Logout clicked"); // console.log("Logout clicked");
// setShowLogoutAlert(true); // setShowLogoutAlert(true);
AlertDefaultSystem({ AlertDefaultSystem({
@@ -27,6 +33,22 @@ export default function Profile_MenuDrawerSection({
}, },
onPressLeft: () => setIsDrawerOpen(false), onPressLeft: () => setIsDrawerOpen(false),
}); });
} else if (item.value === "delete-account") {
console.log("PATH >> ", item.path);
// openBrowser(item.path as any);
AlertDefaultSystem({
title: "Apakah anda yakin ingin menghapus akun ini?",
message:
"Pilih 'Ya' untuk masuk ke halaman penghapusan akun",
textLeft: "Batal",
textRight: "Ya",
onPressRight: async () => {
router.push(item.path as any);
setIsDrawerOpen(false);
},
onPressLeft: () => setIsDrawerOpen(false),
});
} else { } else {
console.log("PATH >> ", item.path); console.log("PATH >> ", item.path);
router.push(item.path as any); router.push(item.path as any);
@@ -43,6 +65,7 @@ export default function Profile_MenuDrawerSection({
label: item.label, label: item.label,
path: item.path as any, path: item.path as any,
color: item.color, color: item.color,
value: item.value,
}))} }))}
columns={4} // Ubah ke 2 jika ingin 2 kolom per baris columns={4} // Ubah ke 2 jika ingin 2 kolom per baris
onPressItem={(item) => handlePress(item as any)} onPressItem={(item) => handlePress(item as any)}

Some files were not shown because too many files have changed in this diff Show More