diff --git a/app/(application)/(user)/investment/(tabs)/_layout.tsx b/app/(application)/(user)/investment/(tabs)/_layout.tsx
index 0e49df0..9272ec9 100644
--- a/app/(application)/(user)/investment/(tabs)/_layout.tsx
+++ b/app/(application)/(user)/investment/(tabs)/_layout.tsx
@@ -1,9 +1,33 @@
+import BackButtonFromNotification from "@/components/Button/BackButtonFromNotification";
import { ICON_SIZE_SMALL } from "@/constants/constans-value";
import { TabsStyles } from "@/styles/tabs-styles";
import { Feather, FontAwesome6, Ionicons } from "@expo/vector-icons";
-import { Tabs } from "expo-router";
+import { router, Tabs, useLocalSearchParams, useNavigation } from "expo-router";
+import { useLayoutEffect } from "react";
export default function InvestmentTabsLayout() {
+ // const navigation = useNavigation();
+
+ // const { from, category } = useLocalSearchParams<{
+ // from?: string;
+ // category?: string;
+ // }>();
+
+ // console.log("from", from);
+ // console.log("category", category);
+
+ // // Atur header secara dinamis
+ // useLayoutEffect(() => {
+ // navigation.setOptions({
+ // headerLeft: () => (
+ //
+ // ),
+ // });
+ // }, [from, router, navigation]);
+
return (
();
+
const [activeCategory, setActiveCategory] = useState(
- "publish"
+ status || "publish"
);
const [listData, setListData] = useState([]);
diff --git a/app/(application)/(user)/investment/[id]/(transaction-flow)/invoice.tsx b/app/(application)/(user)/investment/[id]/(transaction-flow)/invoice.tsx
index e76a5a1..fc9c00d 100644
--- a/app/(application)/(user)/investment/[id]/(transaction-flow)/invoice.tsx
+++ b/app/(application)/(user)/investment/[id]/(transaction-flow)/invoice.tsx
@@ -27,7 +27,6 @@ import Toast from "react-native-toast-message";
export default function InvestmentInvoice() {
const { id } = useLocalSearchParams();
- console.log("[ID]", id);
const [data, setData] = useState({});
const [image, setImage] = useState({
name: "",
@@ -49,7 +48,6 @@ export default function InvestmentInvoice() {
category: "invoice",
});
- console.log("[RES INVOICE]", JSON.stringify(response.data, null, 2));
setData(response.data);
} catch (error) {
console.log("[ERROR]", error);
@@ -64,8 +62,6 @@ export default function InvestmentInvoice() {
imageUri: image?.uri,
});
- console.log("[RESPONSE UPLOAD IMAGE]", responseUploadImage);
-
if (!responseUploadImage?.data?.id) {
Toast.show({
type: "error",
@@ -83,10 +79,6 @@ export default function InvestmentInvoice() {
});
if (response.success) {
- console.log(
- "[RESPONSE UPDATE]",
- JSON.stringify(response.data, null, 2)
- );
Toast.show({
type: "success",
text1: "Berhasil mengunggah bukti transfer",
@@ -210,7 +202,6 @@ export default function InvestmentInvoice() {
pickFile({
allowedType: "image",
setImageUri(file: any) {
- console.log("[IMAGE]", file);
setImage(file);
},
});
@@ -224,7 +215,7 @@ export default function InvestmentInvoice() {
{
handlerSubmitUpdate();
}}
diff --git a/app/(application)/(user)/investment/create.tsx b/app/(application)/(user)/investment/create.tsx
index ca64b6b..d7a9442 100644
--- a/app/(application)/(user)/investment/create.tsx
+++ b/app/(application)/(user)/investment/create.tsx
@@ -167,7 +167,7 @@ export default function InvestmentCreate() {
text1: "Berhasil",
text2: response.message,
});
- router.replace("/investment/portofolio");
+ router.replace("/investment/portofolio?status=review");
} else {
Toast.show({
type: "error",
@@ -224,7 +224,6 @@ export default function InvestmentCreate() {
onPress={() => {
pickFile({
setPdfUri: ({ uri, name, size }) => {
-
setPdf({ uri, name, size });
},
allowedType: "pdf",
@@ -357,7 +356,11 @@ export default function InvestmentCreate() {
)}
- handleSubmit()}>
+ handleSubmit()}
+ >
Simpan
diff --git a/app/(application)/admin/investment/[id]/[status]/index.tsx b/app/(application)/admin/investment/[id]/[status]/index.tsx
index a3dff44..f0ce822 100644
--- a/app/(application)/admin/investment/[id]/[status]/index.tsx
+++ b/app/(application)/admin/investment/[id]/[status]/index.tsx
@@ -20,6 +20,7 @@ import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButt
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
import AdminButtonReview from "@/components/_ShareComponent/Admin/ButtonReview";
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
+import CustomSkeleton from "@/components/_ShareComponent/SkeletonCustom";
import ReportBox from "@/components/Box/ReportBox";
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
@@ -28,6 +29,7 @@ import {
apiAdminInvestmentDetailById,
} from "@/service/api-admin/api-admin-investment";
import { colorBadgeStatus } from "@/utils/colorBadge";
+import { countDownAndCondition } from "@/utils/countDownAndCondition";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash";
@@ -40,91 +42,41 @@ export default function AdminInvestmentDetail() {
const [data, setData] = React.useState(null);
const [isLoading, setLoading] = React.useState(false);
+ const [remind, setRemind] = React.useState({
+ sisa: 0,
+ reminder: false,
+ });
useFocusEffect(
React.useCallback(() => {
onLoadData();
- }, [id])
+ }, [id]),
);
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);
+
+ const duration = response?.data?.MasterPencarianInvestor?.name;
+ const publishTime = response?.data?.countDown;
+
+ const countDown = countDownAndCondition({
+ duration: duration,
+ publishTime: publishTime
+ });
+
+ setRemind({
+ sisa: countDown.durationDay,
+ reminder: countDown.reminder,
+ });
}
} catch (error) {
- console.log(error);
+ console.log("Error", error);
}
};
- const listData = [
- {
- label: "Username",
- value: (data && data?.author?.username) || "-",
- },
- {
- label: "Judul",
- value: (data && data?.title) || "-",
- },
- {
- label: "Status",
- value:
- data && data?.MasterStatusInvestasi?.name ? (
-
- {_.startCase(data?.MasterStatusInvestasi?.name as string)}
-
- ) : (
- "-"
- ),
- },
- {
- label: "Dana Dibutuhkan",
- value: `Rp. ${
- (data && data?.targetDana && formatCurrencyDisplay(data?.targetDana)) ||
- "-"
- }`,
- },
- {
- label: "Harga Perlembar",
- value: `Rp. ${
- (data &&
- data?.hargaLembar &&
- formatCurrencyDisplay(data?.hargaLembar)) ||
- "-"
- }`,
- },
- {
- label: "Total Lembar",
- value:
- (data &&
- data?.totalLembar &&
- formatCurrencyDisplay(data?.totalLembar)) ||
- "-",
- },
- {
- label: "ROI",
- value: `${(data && data?.roi && data?.roi) || 0} %`,
- },
- {
- label: "Pembagian Deviden",
- value: (data && data?.MasterPembagianDeviden?.name) + " bulan" || "-",
- },
- {
- label: "Jadwal Pembagian",
- value: (data && data?.MasterPeriodeDeviden?.name) || "-",
- },
- {
- label: "Pencarian Investor",
- value: (data && data?.MasterPencarianInvestor?.name) + " hari" || "-",
- },
- ];
-
const handlerSubmitPublish = async () => {
try {
setLoading(true);
@@ -134,7 +86,6 @@ export default function AdminInvestmentDetail() {
data: data,
});
- // console.log("[GET ON INVEST]", JSON.stringify(response, null, 2));
if (!response.success) {
Toast.show({
type: "error",
@@ -164,6 +115,16 @@ export default function AdminInvestmentDetail() {
/>
);
+ if (!data) {
+ return (
+ <>
+
+
+
+ >
+ );
+ }
+
return (
<>
@@ -187,7 +148,8 @@ export default function AdminInvestmentDetail() {
label={Sisa Saham}
value={
- {data && formatCurrencyDisplay(data && data?.sisaLembar)} lembar
+ {data && formatCurrencyDisplay(data && data?.sisaLembar)}{" "}
+ lembar
}
/>
@@ -206,13 +168,15 @@ export default function AdminInvestmentDetail() {
- {listData.map((item, i) => (
- {item.label}}
- value={{item.value}}
- />
- ))}
+ {listData({ data: data, reminder: remind.reminder })?.map(
+ (item, i) => (
+ {item.label}}
+ value={{item.value}}
+ />
+ ),
+ )}
@@ -230,7 +194,7 @@ export default function AdminInvestmentDetail() {
}
onPress={() => {
router.push(
- `/(application)/(file)/${data?.prospektusFileId}`
+ `/(application)/(file)/${data?.prospektusFileId}`,
);
}}
>
@@ -259,7 +223,7 @@ export default function AdminInvestmentDetail() {
}
onPress={() => {
router.push(
- `/(application)/(file)/${item?.fileId}`
+ `/(application)/(file)/${item?.fileId}`,
);
}}
>
@@ -299,8 +263,8 @@ export default function AdminInvestmentDetail() {
onReject={() => {
router.push(
`/admin/investment/${id}/reject-input?status=${_.lowerCase(
- data?.MasterStatusInvestasi?.name
- )}`
+ data?.MasterStatusInvestasi?.name,
+ )}`,
);
}}
/>
@@ -343,3 +307,67 @@ export default function AdminInvestmentDetail() {
>
);
}
+
+const listData = ({ data, reminder }: { data: any; reminder: boolean }) => [
+ {
+ label: "Username",
+ value: (data && data?.author?.username) || "-",
+ },
+ {
+ label: "Judul",
+ value: (data && data?.title) || "-",
+ },
+ {
+ label: "Status",
+ value:
+ data && data?.MasterStatusInvestasi?.name ? (
+
+ {reminder
+ ? "Periode Berakhir"
+ : _.startCase(data?.MasterStatusInvestasi?.name as string)}
+
+ ) : (
+ "-"
+ ),
+ },
+ {
+ label: "Dana Dibutuhkan",
+ value: `Rp. ${
+ (data && data?.targetDana && formatCurrencyDisplay(data?.targetDana)) ||
+ "-"
+ }`,
+ },
+ {
+ label: "Harga Perlembar",
+ value: `Rp. ${
+ (data && data?.hargaLembar && formatCurrencyDisplay(data?.hargaLembar)) ||
+ "-"
+ }`,
+ },
+ {
+ label: "Total Lembar",
+ value:
+ (data && data?.totalLembar && formatCurrencyDisplay(data?.totalLembar)) ||
+ "-",
+ },
+ {
+ label: "ROI",
+ value: `${(data && data?.roi && data?.roi) || 0} %`,
+ },
+ {
+ label: "Pembagian Deviden",
+ value: (data && data?.MasterPembagianDeviden?.name) + " bulan" || "-",
+ },
+ {
+ label: "Jadwal Pembagian",
+ value: (data && data?.MasterPeriodeDeviden?.name) || "-",
+ },
+ {
+ label: "Pencarian Investor",
+ value: (data && data?.MasterPencarianInvestor?.name) + " hari" || "-",
+ },
+];
diff --git a/app/(application)/admin/investment/[id]/[status]/transaction-detail.tsx b/app/(application)/admin/investment/[id]/[status]/transaction-detail.tsx
index 6bab71c..583c248 100644
--- a/app/(application)/admin/investment/[id]/[status]/transaction-detail.tsx
+++ b/app/(application)/admin/investment/[id]/[status]/transaction-detail.tsx
@@ -13,6 +13,7 @@ import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButt
import { GridSpan_4_8 } from "@/components/_ShareComponent/GridSpan_4_8";
import GridTwoView from "@/components/_ShareComponent/GridTwoView";
import { MainColor } from "@/constants/color-palet";
+import { useAuth } from "@/hooks/use-auth";
import {
apiAdminInvestmentGetOneInvoiceById,
apiAdminInvestmentUpdateInvoice,
@@ -25,6 +26,7 @@ import { useCallback, useState } from "react";
import Toast from "react-native-toast-message";
export default function AdminInvestmentTransactionDetail() {
+ const { user } = useAuth();
const { id } = useLocalSearchParams();
const [data, setData] = useState(null);
const [isLoading, setLoading] = useState(false);
@@ -32,7 +34,7 @@ export default function AdminInvestmentTransactionDetail() {
useFocusEffect(
useCallback(() => {
onLoadData();
- }, [id])
+ }, [id]),
);
const onLoadData = async () => {
@@ -40,7 +42,6 @@ export default function AdminInvestmentTransactionDetail() {
const response = await apiAdminInvestmentGetOneInvoiceById({
id: id as string,
});
- // console.log("[RESPONSE]", JSON.stringify(response, null, 2));
if (response.success) {
setData(response.data);
}
@@ -92,7 +93,7 @@ export default function AdminInvestmentTransactionDetail() {
router.push(
- `/(application)/(image)/preview-image/${data?.imageId}`
+ `/(application)/(image)/preview-image/${data?.imageId}`,
)
}
>
@@ -109,6 +110,13 @@ export default function AdminInvestmentTransactionDetail() {
}: {
category: "accept" | "deny";
}) => {
+ if (!user?.id) {
+ Toast.show({
+ type: "error",
+ text1: "Gagal update status transaksi",
+ });
+ return;
+ }
try {
setLoading(true);
const response = await apiAdminInvestmentUpdateInvoice({
@@ -117,11 +125,10 @@ export default function AdminInvestmentTransactionDetail() {
data: {
investasiId: data?.investasiId,
lembarTerbeli: data?.lembarTerbeli,
+ senderId: user?.id as any,
},
});
- // console.log("[RESPONSE SUBMIT]", JSON.stringify(response, null, 2));
-
if (!response.success) {
Toast.show({
type: "error",
@@ -153,6 +160,7 @@ export default function AdminInvestmentTransactionDetail() {
styleRight={{ paddingLeft: 10 }}
leftIcon={
{
AlertDefaultSystem({
@@ -198,8 +207,8 @@ export default function AdminInvestmentTransactionDetail() {
} else if (data?.StatusInvoice?.name === "Gagal") {
return (
<>
- router.back()}>
- Gagal
+ router.back()}>
+ Transaksi telah gagal
>
);
diff --git a/app/(application)/admin/investment/[id]/reject-input.tsx b/app/(application)/admin/investment/[id]/reject-input.tsx
index c7361e0..444a973 100644
--- a/app/(application)/admin/investment/[id]/reject-input.tsx
+++ b/app/(application)/admin/investment/[id]/reject-input.tsx
@@ -7,34 +7,39 @@ import {
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
-import { apiAdminInvestasiUpdateByStatus, apiAdminInvestmentDetailById } from "@/service/api-admin/api-admin-investment";
+import { useAuth } from "@/hooks/use-auth";
+import {
+ apiAdminInvestasiUpdateByStatus,
+ apiAdminInvestmentDetailById,
+} from "@/service/api-admin/api-admin-investment";
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import { useCallback, useState } from "react";
import Toast from "react-native-toast-message";
export default function AdminInvestmentRejectInput() {
+ const { user } = useAuth();
const { id, status } = useLocalSearchParams();
console.log("[STATUS]", status);
const [value, setValue] = useState(null);
- const [isLoading , setLoading] = useState(false)
+ 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);
+ 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) {
@@ -45,12 +50,23 @@ export default function AdminInvestmentRejectInput() {
return;
}
+ if (!user?.id) {
+ Toast.show({
+ type: "error",
+ text1: "User tidak ditemukan",
+ });
+ return;
+ }
+
try {
- setLoading(true)
+ setLoading(true);
const response = await apiAdminInvestasiUpdateByStatus({
id: id as string,
status: "reject",
- data: value,
+ data: {
+ catatan: value,
+ senderId: user?.id as string,
+ },
});
console.log("[RESPONSE]", JSON.stringify(response, null, 2));
@@ -76,7 +92,7 @@ export default function AdminInvestmentRejectInput() {
} catch (error) {
console.error(["ERROR"], error);
} finally {
- setLoading(false)
+ setLoading(false);
}
};
diff --git a/app/(application)/admin/investment/[status]/status.tsx b/app/(application)/admin/investment/[status]/status.tsx
index d3c644c..c84c8ad 100644
--- a/app/(application)/admin/investment/[status]/status.tsx
+++ b/app/(application)/admin/investment/[status]/status.tsx
@@ -22,8 +22,6 @@ import { Divider } from "react-native-paper";
export default function AdminInvestmentStatus() {
const { status } = useLocalSearchParams();
- console.log("[STATUS]", status);
-
const [listData, setListData] = React.useState(null);
const [loadData, setLoadingData] = React.useState(false);
const [search, setSearch] = React.useState("");
@@ -41,7 +39,7 @@ export default function AdminInvestmentStatus() {
category: status as "publish" | "review" | "reject",
search,
});
- console.log("[LIST DATA]", JSON.stringify(response, null, 2));
+
if (response.success) {
setListData(response.data);
}
diff --git a/screens/Invesment/BoxBerandaSection.tsx b/screens/Invesment/BoxBerandaSection.tsx
index 5e6292a..4113bb3 100644
--- a/screens/Invesment/BoxBerandaSection.tsx
+++ b/screens/Invesment/BoxBerandaSection.tsx
@@ -7,7 +7,6 @@ import {
TextCustom,
} from "@/components";
import API_STRORAGE from "@/constants/base-url-api-strorage";
-import { MainColor } from "@/constants/color-palet";
import DUMMY_IMAGE from "@/constants/dummy-image-value";
import { countDownAndCondition } from "@/utils/countDownAndCondition";
import { Ionicons } from "@expo/vector-icons";
@@ -22,8 +21,6 @@ export default function Investment_BoxBerandaSection({
id: string;
data: any;
}) {
- // console.log("[DATA By one]", JSON.stringify(data, null, 2));
-
const [value, setValue] = useState({
sisa: 0,
reminder: false,
@@ -33,8 +30,6 @@ export default function Investment_BoxBerandaSection({
updateCountDown();
}, [data]);
- console.log("[DATA BERANDA]", JSON.stringify(data, null, 2));
-
const updateCountDown = () => {
const countDown = countDownAndCondition({
duration: data?.pencarianInvestor,
diff --git a/service/api-admin/api-admin-investment.ts b/service/api-admin/api-admin-investment.ts
index 5bb57d3..510bd9c 100644
--- a/service/api-admin/api-admin-investment.ts
+++ b/service/api-admin/api-admin-investment.ts
@@ -1,3 +1,4 @@
+import { typeRejectedData } from "@/types/type-collect-other";
import { apiConfig } from "../api-config";
export async function apiAdminInvestment({
@@ -38,7 +39,7 @@ export async function apiAdminInvestasiUpdateByStatus({
}: {
id: string;
status: "publish" | "review" | "reject";
- data: any;
+ data: typeRejectedData;
}) {
try {
const response = await apiConfig.put(
@@ -97,6 +98,7 @@ export async function apiAdminInvestmentUpdateInvoice({
data: {
investasiId: string;
lembarTerbeli: number;
+ senderId: string
};
}) {
try {
diff --git a/utils/pickFile.ts b/utils/pickFile.ts
index 613a7d7..68f279c 100644
--- a/utils/pickFile.ts
+++ b/utils/pickFile.ts
@@ -1,6 +1,6 @@
import * as ImagePicker from "expo-image-picker";
import * as DocumentPicker from "expo-document-picker";
-import { Alert } from "react-native";
+import { Alert, Platform } from "react-native";
const ALLOWED_IMAGE_EXTENSIONS = ["jpg", "jpeg", "png"];
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
@@ -33,22 +33,52 @@ export default async function pickFile({
await pickImage(setImageUri, aspectRatio);
} else {
// Jika tidak, tawarkan pilihan rasio (default [4,3])
- showAspectRatioChoice(setImageUri);
+ // 🚀 Hanya tampilkan pilihan rasio di ANDROID
+ if (Platform.OS === "android") {
+ showAspectRatioChoice(setImageUri);
+ } else {
+ // iOS: langsung buka galeri dengan default [4, 3]
+ await pickImage(setImageUri, [4, 3]);
+ }
}
} else if (allowedType === "pdf") {
await pickPdf(setPdfUri);
} else {
// Mode fleksibel: tampilkan pilihan
- Alert.alert(
- "Pilih Jenis File",
- "Pilih sumber file yang ingin diunggah:",
- [
- { text: "Batal", style: "cancel" },
- { text: "Dokumen (PDF)", onPress: () => pickPdf(setPdfUri) },
- { text: "Gambar", onPress: () => pickImage(setImageUri, aspectRatio) },
- ],
- { cancelable: true }
- );
+ // Alert.alert(
+ // "Pilih Jenis File",
+ // "Pilih sumber file yang ingin diunggah:",
+ // [
+ // { text: "Batal", style: "cancel" },
+ // { text: "Dokumen (PDF)", onPress: () => pickPdf(setPdfUri) },
+ // { text: "Gambar", onPress: () => pickImage(setImageUri, aspectRatio) },
+ // ],
+ // { cancelable: true }
+ // );
+ if (Platform.OS === "android") {
+ Alert.alert(
+ "Pilih Jenis File",
+ "Pilih sumber file yang ingin diunggah:",
+ [
+ { text: "Batal", style: "cancel" },
+ { text: "Dokumen (PDF)", onPress: () => pickPdf(setPdfUri) },
+ { text: "Gambar", onPress: () => showAspectRatioChoice(setImageUri) },
+ ],
+ { cancelable: true }
+ );
+ } else {
+ // iOS: Langsung pakai default [4,3] untuk gambar
+ Alert.alert(
+ "Pilih Jenis File",
+ "Pilih sumber file yang ingin diunggah:",
+ [
+ { text: "Batal", style: "cancel" },
+ { text: "Dokumen (PDF)", onPress: () => pickPdf(setPdfUri) },
+ { text: "Gambar", onPress: () => pickImage(setImageUri, [4, 3]) },
+ ],
+ { cancelable: true }
+ );
+ }
}
}