New repo mobile after delete ! #1

Merged
bagasbanuna merged 233 commits from api/24-oct-25 into main 2025-10-27 11:32:16 +08:00
519 changed files with 43303 additions and 13537 deletions
Showing only changes of commit c2acb97a37 - Show all commits

View File

@@ -2,18 +2,46 @@ import {
BaseBox,
FloatingButton,
Grid,
LoaderCustom,
ProgressCustom,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import API_STRORAGE from "@/constants/base-url-api-strorage";
import DUMMY_IMAGE from "@/constants/dummy-image-value";
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 } from "expo-router";
import { router, useFocusEffect } from "expo-router";
import _ from "lodash";
import { useCallback, useState } from "react";
import { View } from "react-native";
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();
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
@@ -21,40 +49,77 @@ export default function InvestmentBursa() {
<FloatingButton onPress={() => router.push("/investment/create")} />
}
>
{Array.from({ length: 10 }).map((_, index) => (
<BaseBox key={index} paddingTop={7} paddingBottom={7} href={`/investment/${index}`}>
<Grid>
<Grid.Col span={5}>
<Image
source={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}>
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>
<ProgressCustom value={index % 5 * 20} size="lg" />
<TextCustom>
Sisa waktu: {dayjs().diff(dayjs(), "day")} hari
</TextCustom>
</StackCustom>
</Grid.Col>
</Grid>
</BaseBox>
))}
{loadingList ? (
<LoaderCustom />
) : _.isEmpty(list) ? (
<TextCustom>Belum ada data</TextCustom>
) : (
list?.map((item: any, index: number) => (
<BaseBox
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>
);
}
// <View style={{ padding: 20, gap: 16 }}>
// <TextCustom>Progress 70%</TextCustom>
// <ProgressCustom value={70} color="primary" size="md" />
@@ -78,4 +143,4 @@ export default function InvestmentBursa() {
// <ProgressCustom value={90} color="warning" size="lg" showLabel={false} />
// <ProgressCustom value={null} color="error" size="sm" label="Loading..." />
// </View>;
// </View>;

View File

@@ -10,10 +10,11 @@ import { IconDocument, IconEdit, IconNews } from "@/components/_Icon";
import { IMenuDrawerItem } from "@/components/_Interface/types";
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
import { useAuth } from "@/hooks/use-auth";
import Investment_ButtonInvestasiSection from "@/screens/Invesment/ButtonInvestasiSection";
import Invesment_ComponentBoxOnBottomDetail from "@/screens/Invesment/ComponentBoxOnBottomDetail";
import Invesment_DetailDataPublishSection from "@/screens/Invesment/DetailDataPublishSection";
import { apiInvestmentGetById } from "@/service/api-client/api-investment";
import { apiInvestmentGetOne } from "@/service/api-client/api-investment";
import { AntDesign, MaterialIcons } from "@expo/vector-icons";
import {
router,
@@ -25,6 +26,7 @@ import _ from "lodash";
import { useCallback, useState } from "react";
export default function InvestmentDetailStatus() {
const { user } = useAuth();
const { id, status } = useLocalSearchParams();
const [openDrawerDraft, setOpenDrawerDraft] = useState(false);
const [openDrawerPublish, setOpenDrawerPublish] = useState(false);
@@ -39,7 +41,7 @@ export default function InvestmentDetailStatus() {
const onLoadData = async () => {
try {
const response = await apiInvestmentGetById({
const response = await apiInvestmentGetOne({
id: id as string,
});
@@ -70,7 +72,7 @@ export default function InvestmentDetailStatus() {
);
const buttonSection = (
<Investment_ButtonInvestasiSection id={id as string} isMine={false} />
<Investment_ButtonInvestasiSection id={id as string} isMine={user?.id === data?.author?.id} />
);
return (

View File

@@ -14,7 +14,7 @@ import {
} from "@/components";
import DIRECTORY_ID from "@/constants/directory-id";
import {
apiInvestmentGetById,
apiInvestmentGetOne,
apiInvestmentUpdateData,
} from "@/service/api-client/api-investment";
import { deleteFileService, uploadFileService } from "@/service/upload-service";
@@ -40,7 +40,7 @@ export default function InvestmentEditProspectus() {
const onLoadData = async () => {
try {
setLoadingGet(true);
const response = await apiInvestmentGetById({
const response = await apiInvestmentGetOne({
id: id as string,
});
setData(response.data);

View File

@@ -14,7 +14,7 @@ import {
import API_STRORAGE from "@/constants/base-url-api-strorage";
import DIRECTORY_ID from "@/constants/directory-id";
import {
apiInvestmentGetById,
apiInvestmentGetOne,
apiInvestmentUpdateData,
} from "@/service/api-client/api-investment";
import { apiMasterInvestment } from "@/service/api-client/api-master";
@@ -90,7 +90,7 @@ export default function InvestmentEdit() {
const onLoadData = async () => {
try {
const response = await apiInvestmentGetById({
const response = await apiInvestmentGetOne({
id: id as string,
});
setData(response.data);

View File

@@ -9,18 +9,45 @@ import { IconDocument, IconEdit, IconNews } from "@/components/_Icon";
import { IMenuDrawerItem } from "@/components/_Interface/types";
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_MEDIUM } from "@/constants/constans-value";
import { useAuth } from "@/hooks/use-auth";
import Investment_ButtonInvestasiSection from "@/screens/Invesment/ButtonInvestasiSection";
import Invesment_ComponentBoxOnBottomDetail from "@/screens/Invesment/ComponentBoxOnBottomDetail";
import Invesment_DetailDataPublishSection from "@/screens/Invesment/DetailDataPublishSection";
import { apiInvestmentGetOne } from "@/service/api-client/api-investment";
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 { useState } from "react";
import { useCallback, useState } from "react";
export default function InvestmentDetail() {
const { user } = useAuth();
const { id, status } = useLocalSearchParams();
const [openDrawerDraft, setOpenDrawerDraft] = 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 apiInvestmentGetOne({
id: id as string,
});
setData(response.data);
} catch (error) {
console.log("[ERROR]", error);
}
};
const handlePressDraft = (item: IMenuDrawerItem) => {
console.log("PATH >> ", item.path);
@@ -37,11 +64,14 @@ export default function InvestmentDetail() {
const bottomSection = (
<Invesment_ComponentBoxOnBottomDetail
id={id as string}
status={'publish'}
prospectusId={data?.prospektusFileId}
status={"publish"}
/>
);
const buttonSection = <Investment_ButtonInvestasiSection id={id as string} isMine={true} />;
const buttonSection = (
<Investment_ButtonInvestasiSection id={id as string} isMine={user?.id === data?.author?.id} />
);
return (
<>
@@ -61,6 +91,7 @@ export default function InvestmentDetail() {
<ViewWrapper>
<Invesment_DetailDataPublishSection
status={"publish"}
data={data}
bottomSection={bottomSection}
buttonSection={buttonSection}
/>

View File

@@ -44,30 +44,30 @@ const listDataPublishInvesment = ({ data }: { data: any }) => [
},
{
label: "Harga Per Lembar",
value: data?.hargaPerLembar,
value: `Rp. ${formatCurrencyDisplay(data?.hargaLembar) || "-"}`,
},
{
label: "Return Of Investment (ROI)",
value: data?.roi + " %",
value: `${data?.roi || "-"} %`,
},
{
label: "Total Lembar",
value: data?.totalLembar,
value: data?.totalLembar || "-",
},
{
label: "Sisa Lembar",
value: data?.sisaLembar,
},
{
label: "Jadwal Pembagian",
value: data?.jadwalPembagian,
},
{
label: "Pembagian Deviden",
value: data?.pembagianDeviden,
value: data?.sisaLembar || "-",
},
{
label: "Pencarian Investor",
value: data?.pencarianInvestor,
value: (data && data?.MasterPencarianInvestor?.name + " hari") || "-",
},
{
label: "Jadwal Pembagian",
value: (data && data?.MasterPembagianDeviden?.name + " bulan") || "-",
},
{
label: "Pembagian Deviden",
value: data?.MasterPeriodeDeviden?.name || "-",
},
];

View File

@@ -1,5 +1,7 @@
import {
AvatarUsernameAndOtherComponent,
BaseBox,
BoxWithHeaderSection,
DummyLandscapeImage,
Grid,
Spacing,
@@ -10,19 +12,30 @@ import { View } from "react-native";
export default function Invesment_BoxDetailDataSection({
title,
author,
imageId,
data,
bottomSection,
}: {
title?: string;
author?: any;
imageId?: string;
data: any;
bottomSection?: React.ReactNode;
}) {
return (
<>
<BaseBox paddingBottom={0}>
<BoxWithHeaderSection>
<StackCustom gap={"xs"}>
{author && (
<AvatarUsernameAndOtherComponent
avatar={author?.Profile?.imageId}
name={author?.username}
rightComponent={""}
withBottomLine={true}
/>
)}
<DummyLandscapeImage imageId={imageId} />
<Spacing />
<TextCustom align="center" size="xlarge" bold>
@@ -46,7 +59,7 @@ export default function Invesment_BoxDetailDataSection({
<Spacing />
{bottomSection}
</StackCustom>
</BaseBox>
</BoxWithHeaderSection>
</>
);
}

View File

@@ -1,13 +1,13 @@
import { BaseBox, StackCustom, TextCustom, ProgressCustom } from "@/components";
export default function Invesment_BoxProgressSection({status}: {status: string}) {
export default function Invesment_BoxProgressSection({progress, status}: {progress: number, status: string}) {
return (
<>
{status === "publish" && (
<BaseBox>
<StackCustom>
<TextCustom bold>Progress Saham</TextCustom>
<ProgressCustom value={70} size="lg" />
<ProgressCustom label={progress + "%"} value={progress} size="lg" />
</StackCustom>
</BaseBox>
)}

View File

@@ -8,9 +8,12 @@ export default function Investment_ButtonInvestasiSection({
id: string;
isMine: boolean;
}) {
console.log("[IS MINE]", isMine);
return (
<>
{isMine ? (
<ButtonCustom disabled>Investasi Ini Milik Anda</ButtonCustom>
) : (
<ButtonCustom
onPress={() => {
router.navigate(`/investment/${id}/(transaction-flow)`);
@@ -18,8 +21,6 @@ export default function Investment_ButtonInvestasiSection({
>
Beli Saham
</ButtonCustom>
) : (
<ButtonCustom disabled>Investasi Ini Milik Anda</ButtonCustom>
)}
</>
);

View File

@@ -18,7 +18,6 @@ export default function Invesment_ComponentBoxOnBottomDetail({
prospectusId: string;
status: string;
}) {
return (
<>
{status === "publish" ? (
@@ -28,7 +27,7 @@ export default function Invesment_ComponentBoxOnBottomDetail({
<BaseBox
backgroundColor={AccentColor.blue}
style={{ borderColor: AccentColor.softblue, borderWidth: 1 }}
href={`/(file)/${id}`}
href={`/(file)/${prospectusId}`}
>
<StackCustom>
<TextCustom align="center">Prospektus</TextCustom>

View File

@@ -19,13 +19,14 @@ export default function Invesment_DetailDataPublishSection({
bottomSection?: React.ReactNode;
buttonSection?: React.ReactNode;
}) {
// console.log("[DATA DETAIL]", JSON.stringify(data, null, 2));
return (
<>
<StackCustom gap={"sm"}>
<Invesment_BoxProgressSection status={status as string} />
<Invesment_BoxProgressSection progress={data?.progress} status={status as string} />
<Invesment_BoxDetailDataSection
title={data?.title}
author={data?.author}
imageId={data?.imageId}
data={
status === "publish"

View File

@@ -28,7 +28,7 @@ export async function apiInvestmentGetByStatus({
}
}
export async function apiInvestmentGetById({ id }: { id: string }) {
export async function apiInvestmentGetOne({ id }: { id: string }) {
try {
const response = await apiConfig.get(`/mobile/investment/${id}`);
return response.data;
@@ -117,11 +117,7 @@ export async function apiInvestmentGetDocument({
}
}
export async function apiInvestmentDeleteDocument({
id,
}: {
id: string;
}) {
export async function apiInvestmentDeleteDocument({ id }: { id: string }) {
try {
const response = await apiConfig.delete(
`/mobile/investment/${id}/document`
@@ -131,3 +127,13 @@ export async function apiInvestmentDeleteDocument({
throw error;
}
}
export async function apiInvestmentGetAll() {
try {
const response = await apiConfig.get(`/mobile/investment`);
return response.data;
} catch (error) {
throw error;
}
}