Fix Loaddata Invesment & Clearing code

UI – Investment (User)
- app/(application)/(user)/investment/(tabs)/index.tsx
- app/(application)/(user)/investment/(tabs)/portofolio.tsx
- app/(application)/(user)/investment/(tabs)/transaction.tsx
- app/(application)/(user)/investment/[id]/(document)/list-of-document.tsx
- app/(application)/(user)/investment/[id]/(document)/recap-of-document.tsx
- app/(application)/(user)/investment/[id]/(transaction-flow)/invoice.tsx
- app/(application)/(user)/investment/[id]/(transaction-flow)/select-bank.tsx

Screens – Investment
- screens/Invesment/ButtonStatusSection.tsx
- screens/Invesment/Document/RecapBoxDetail.tsx
- screens/Invesment/Document/ScreenListDocument.tsx
- screens/Invesment/Document/ScreenRecap.tsx
- screens/Invesment/ScreenBursa.tsx
- screens/Invesment/ScreenPortofolio.tsx
- screens/Invesment/ScreenTransaction.tsx

Profile
- app/(application)/(user)/profile/[id]/detail-blocked.tsx

API Client
- service/api-client/api-investment.ts

Docs
- docs/prompt-for-qwen-code.md

### No issue
This commit is contained in:
2026-02-06 17:27:12 +08:00
parent c570a19d84
commit 83fa277e03
17 changed files with 673 additions and 746 deletions

View File

@@ -1,56 +1,9 @@
import {
FloatingButton,
LoaderCustom,
ViewWrapper
} from "@/components";
import NoDataText from "@/components/_ShareComponent/NoDataText";
import Investment_BoxBerandaSection from "@/screens/Invesment/BoxBerandaSection";
import { apiInvestmentGetAll } from "@/service/api-client/api-investment";
import { router, useFocusEffect } from "expo-router";
import _ from "lodash";
import { useCallback, useState } from "react";
import Investment_ScreenBursa from "@/screens/Invesment/ScreenBursa";
export default function InvestmentBursa() {
const [list, setList] = useState<any[] | null>(null);
const [loadingList, setLoadingList] = useState(false);
useFocusEffect(
useCallback(() => {
onLoadList();
}, [])
);
const onLoadList = async () => {
try {
setLoadingList(true);
const response = await apiInvestmentGetAll({
category: "bursa"
});
// console.log("[DATA LIST]", JSON.stringify(response.data, null, 2));
setList(response.data);
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadingList(false);
}
};
return (
<ViewWrapper
hideFooter
floatingButton={
<FloatingButton onPress={() => router.push("/investment/create")} />
}
>
{loadingList ? (
<LoaderCustom />
) : _.isEmpty(list) ? (
<NoDataText />
) : (
list?.map((item: any, index: number) => (
<Investment_BoxBerandaSection id={item.id} data={item} key={index} />
))
)}
</ViewWrapper>
<>
<Investment_ScreenBursa />
</>
);
}

View File

@@ -1,82 +1,10 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
LoaderCustom,
ScrollableCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import { useAuth } from "@/hooks/use-auth";
import { dummyMasterStatus } from "@/lib/dummy-data/_master/status";
import Investment_StatusBox from "@/screens/Invesment/StatusBox";
import { apiInvestmentGetByStatus } from "@/service/api-client/api-investment";
import { useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash";
import { useCallback, useState } from "react";
import Investment_ScreenPortofolio from "@/screens/Invesment/ScreenPortofolio";
export default function InvestmentPortofolio() {
const { user } = useAuth();
const { status } = useLocalSearchParams<{ status?: string }>();
const [activeCategory, setActiveCategory] = useState<string | null>(
status || "publish"
);
const [listData, setListData] = useState<any[]>([]);
const [loadingList, setLoadingList] = useState(false);
useFocusEffect(
useCallback(() => {
onLoadData();
}, [user?.id, activeCategory])
);
const onLoadData = async () => {
try {
setLoadingList(true);
const response = await apiInvestmentGetByStatus({
authorId: user?.id as string,
status: activeCategory as string,
});
setListData(response.data);
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadingList(false);
}
};
const handlePress = (item: any) => {
setActiveCategory(item.value);
// tambahkan logika lain seperti filter dsb.
};
const scrollComponent = (
<ScrollableCustom
data={dummyMasterStatus.map((e, i) => ({
id: i,
label: e.label,
value: e.value,
}))}
onButtonPress={handlePress}
activeId={activeCategory as any}
/>
);
return (
<ViewWrapper headerComponent={scrollComponent} hideFooter>
{loadingList ? (
<LoaderCustom />
) : _.isEmpty(listData) ? (
<TextCustom align="center">Tidak ada data {activeCategory}</TextCustom>
) : (
listData.map((item: any, index: number) => (
<Investment_StatusBox
key={index}
data={item}
status={activeCategory as string}
href={`/investment/${item.id}/${activeCategory}/detail`}
/>
))
)}
</ViewWrapper>
<>
<Investment_ScreenPortofolio />
</>
);
}

View File

@@ -1,124 +1,10 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
BadgeCustom,
BaseBox,
Grid,
LoaderCustom,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import NoDataText from "@/components/_ShareComponent/NoDataText";
import { useAuth } from "@/hooks/use-auth";
import { apiInvestmentGetInvoice } from "@/service/api-client/api-investment";
import { GStyles } from "@/styles/global-styles";
import { formatChatTime } from "@/utils/formatChatTime";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import { router, useFocusEffect } from "expo-router";
import _ from "lodash";
import { useCallback, useState } from "react";
import { View } from "react-native";
import Investment_ScreenTransaction from "@/screens/Invesment/ScreenTransaction";
export default function InvestmentTransaction() {
const { user } = useAuth();
const [list, setList] = useState<any>([]);
const [loadList, setLoadList] = useState<boolean>(false);
useFocusEffect(
useCallback(() => {
onLoadList();
}, [user?.id])
);
const onLoadList = async () => {
try {
setLoadList(true);
const response = await apiInvestmentGetInvoice({
authorId: user?.id as string,
category: "transaction",
});
console.log("[RESPONSE LIST]", JSON.stringify(response.data, null, 2));
setList(response.data);
} catch (error) {
console.log("[ERROR]", error);
} finally {
setLoadList(false);
}
};
const handlerColor = (status: string) => {
if (status === "menunggu") {
return "orange";
} else if (status === "proses") {
return "white";
} else if (status === "berhasil") {
return "green";
} else if (status === "gagal") {
return "red";
}
};
const handlePress = ({ id, status }: { id: string; status: string }) => {
if (status === "menunggu") {
router.push(`/investment/${id}/(transaction-flow)/invoice`);
} else if (status === "proses") {
router.push(`/investment/${id}/(transaction-flow)/process`);
} else if (status === "berhasil") {
router.push(`/investment/${id}/(transaction-flow)/success`);
} else if (status === "gagal") {
router.push(`/investment/${id}/(transaction-flow)/failed`);
}
};
return (
<ViewWrapper hideFooter>
{loadList ? (
<LoaderCustom />
) : _.isEmpty(list) ? (
<NoDataText/>
) : (
list.map((item: any, i: number) => (
<BaseBox
key={i}
paddingTop={7}
paddingBottom={7}
onPress={() => {
handlePress({
id: item.id,
status: _.lowerCase(item.statusInvoice),
});
}}
>
<Grid>
<Grid.Col span={6}>
<StackCustom gap={"xs"}>
<TextCustom truncate>{item?.title || "-"}</TextCustom>
<TextCustom color="gray" size="small">
{formatChatTime(item?.createdAt)}
</TextCustom>
</StackCustom>
</Grid.Col>
<Grid.Col span={1}>
<View />
</Grid.Col>
<Grid.Col span={5} style={{ alignItems: "flex-end" }}>
<StackCustom gap={"xs"}>
<TextCustom bold truncate>
Rp. {formatCurrencyDisplay(item?.nominal) || "-"}
</TextCustom>
<BadgeCustom
variant="light"
color={handlerColor(_.lowerCase(item.statusInvoice))}
style={GStyles.alignSelfFlexEnd}
>
{item?.statusInvoice || "-"}
</BadgeCustom>
</StackCustom>
</Grid.Col>
</Grid>
</BaseBox>
))
)}
</ViewWrapper>
<>
<Investment_ScreenTransaction />
</>
);
}