feat: Complete User Phase 9 Investment screens migration + note known upload issue

- Migrate 24 investment screens to OS_Wrapper (tabs, list, detail, forms, transaction flow)
- Add contentPadding={PADDING_INLINE} to 9 list/tabs screens for consistent spacing
- Add enableKeyboardHandling to 6 form screens
- Fix investment tabs layout height to use OS_IOS_HEIGHT/OS_ANDROID_HEIGHT constants
- Update TASK-005 with known issue: upload image returns 500 error in dev env
- Note: Investment feature not fully complete - upload issue needs investigation tomorrow

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
2026-04-13 17:56:49 +08:00
parent 2f87776d8b
commit eb64c30d49
27 changed files with 153 additions and 123 deletions

View File

@@ -1,5 +1,5 @@
import BackButtonFromNotification from "@/components/Button/BackButtonFromNotification"; import BackButtonFromNotification from "@/components/Button/BackButtonFromNotification";
import { ICON_SIZE_SMALL } from "@/constants/constans-value"; import { ICON_SIZE_SMALL, OS_ANDROID_HEIGHT, OS_IOS_HEIGHT } from "@/constants/constans-value";
import { TabsStyles } from "@/styles/tabs-styles"; import { TabsStyles } from "@/styles/tabs-styles";
import { Feather, FontAwesome6, Ionicons } from "@expo/vector-icons"; import { Feather, FontAwesome6, Ionicons } from "@expo/vector-icons";
import { router, Tabs, useLocalSearchParams, useNavigation } from "expo-router"; import { router, Tabs, useLocalSearchParams, useNavigation } from "expo-router";
@@ -40,12 +40,12 @@ function InvestmentTabsWrapper() {
ios: { ios: {
borderTopWidth: 0, borderTopWidth: 0,
paddingTop: 12, paddingTop: 12,
height: 80, height: OS_IOS_HEIGHT,
}, },
android: { android: {
borderTopWidth: 0, borderTopWidth: 0,
paddingTop: 5, paddingTop: 5,
height: 70 + paddingBottom, height: OS_ANDROID_HEIGHT + paddingBottom,
}, },
}), }),
}} }}

View File

@@ -5,11 +5,11 @@ import {
ButtonCustom, ButtonCustom,
CenterCustom, CenterCustom,
InformationBox, InformationBox,
OS_Wrapper,
Spacing, Spacing,
StackCustom, StackCustom,
TextCustom, TextCustom,
TextInputCustom, TextInputCustom,
ViewWrapper,
} from "@/components"; } from "@/components";
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
import DIRECTORY_ID from "@/constants/directory-id"; import DIRECTORY_ID from "@/constants/directory-id";
@@ -83,9 +83,12 @@ export default function InvestmentAddDocument() {
); );
return ( return (
<> <OS_Wrapper
<ViewWrapper footerComponent={buttonFooter}> enableKeyboardHandling
<StackCustom gap={"xs"}> contentPaddingBottom={250}
footerComponent={buttonFooter}
>
<StackCustom gap={"xs"}>
<InformationBox text="File dokumen bersifat opsional, jika memang ada file yang bisa membantu meyakinkan investor. Anda bisa mengupload nya." /> <InformationBox text="File dokumen bersifat opsional, jika memang ada file yang bisa membantu meyakinkan investor. Anda bisa mengupload nya." />
<Spacing /> <Spacing />
<TextInputCustom <TextInputCustom
@@ -124,7 +127,6 @@ export default function InvestmentAddDocument() {
Upload Upload
</ButtonCenteredOnly> </ButtonCenteredOnly>
</StackCustom> </StackCustom>
</ViewWrapper> </OS_Wrapper>
</>
); );
} }

View File

@@ -6,11 +6,11 @@ import {
ButtonCustom, ButtonCustom,
CenterCustom, CenterCustom,
InformationBox, InformationBox,
OS_Wrapper,
Spacing, Spacing,
StackCustom, StackCustom,
TextCustom, TextCustom,
TextInputCustom, TextInputCustom,
ViewWrapper,
} from "@/components"; } from "@/components";
import DIRECTORY_ID from "@/constants/directory-id"; import DIRECTORY_ID from "@/constants/directory-id";
import { import {
@@ -105,9 +105,12 @@ export default function InvestmentEditDocument() {
); );
return ( return (
<> <OS_Wrapper
<ViewWrapper footerComponent={buttonFooter}> enableKeyboardHandling
<StackCustom gap={"xs"}> contentPaddingBottom={250}
footerComponent={buttonFooter}
>
<StackCustom gap={"xs"}>
<InformationBox text="File dokumen bersifat opsional, jika memang ada file yang bisa membantu meyakinkan investor. Anda bisa mengupload nya." /> <InformationBox text="File dokumen bersifat opsional, jika memang ada file yang bisa membantu meyakinkan investor. Anda bisa mengupload nya." />
<Spacing /> <Spacing />
<TextInputCustom <TextInputCustom
@@ -142,7 +145,6 @@ export default function InvestmentEditDocument() {
Upload Upload
</ButtonCenteredOnly> </ButtonCenteredOnly>
</StackCustom> </StackCustom>
</ViewWrapper> </OS_Wrapper>
</>
); );
} }

View File

@@ -6,9 +6,9 @@ import {
DrawerCustom, DrawerCustom,
Grid, Grid,
MenuDrawerDynamicGrid, MenuDrawerDynamicGrid,
OS_Wrapper,
StackCustom, StackCustom,
TextCustom, TextCustom,
ViewWrapper,
} from "@/components"; } from "@/components";
import AppHeader from "@/components/_ShareComponent/AppHeader"; import AppHeader from "@/components/_ShareComponent/AppHeader";
import { IconDocument, IconEdit, IconNews } from "@/components/_Icon"; import { IconDocument, IconEdit, IconNews } from "@/components/_Icon";
@@ -93,7 +93,7 @@ export default function InvestmentDetailHolding() {
}} }}
/> />
<ViewWrapper> <OS_Wrapper>
<BaseBox> <BaseBox>
<StackCustom gap={"xs"}> <StackCustom gap={"xs"}>
<Grid> <Grid>
@@ -124,7 +124,7 @@ export default function InvestmentDetailHolding() {
status={"publish"} status={"publish"}
bottomSection={bottomSection} bottomSection={bottomSection}
/> />
</ViewWrapper> </OS_Wrapper>
{/* ========= Draft Drawer ========= */} {/* ========= Draft Drawer ========= */}
<DrawerCustom <DrawerCustom

View File

@@ -7,9 +7,9 @@ import {
DrawerCustom, DrawerCustom,
DummyLandscapeImage, DummyLandscapeImage,
MenuDrawerDynamicGrid, MenuDrawerDynamicGrid,
OS_Wrapper,
StackCustom, StackCustom,
TextCustom, TextCustom,
ViewWrapper,
} from "@/components"; } from "@/components";
import AppHeader from "@/components/_ShareComponent/AppHeader"; import AppHeader from "@/components/_ShareComponent/AppHeader";
import { IconTrash } from "@/components/_Icon/IconTrash"; import { IconTrash } from "@/components/_Icon/IconTrash";
@@ -70,7 +70,7 @@ export default function InvestmentNews() {
), ),
}} }}
/> />
<ViewWrapper> <OS_Wrapper>
<BaseBox> <BaseBox>
<StackCustom> <StackCustom>
{data && data?.imageId && ( {data && data?.imageId && (
@@ -82,7 +82,7 @@ export default function InvestmentNews() {
<TextCustom>{(data && data?.deskripsi) || "-"}</TextCustom> <TextCustom>{(data && data?.deskripsi) || "-"}</TextCustom>
</StackCustom> </StackCustom>
</BaseBox> </BaseBox>
</ViewWrapper> </OS_Wrapper>
<DrawerCustom <DrawerCustom
isVisible={openDrawer} isVisible={openDrawer}

View File

@@ -3,11 +3,11 @@ import {
ButtonCustom, ButtonCustom,
InformationBox, InformationBox,
LandscapeFrameUploaded, LandscapeFrameUploaded,
OS_Wrapper,
Spacing, Spacing,
StackCustom, StackCustom,
TextAreaCustom, TextAreaCustom,
TextInputCustom, TextInputCustom,
ViewWrapper,
} from "@/components"; } from "@/components";
import DIRECTORY_ID from "@/constants/directory-id"; import DIRECTORY_ID from "@/constants/directory-id";
import { apiInvestmentCreateNews } from "@/service/api-client/api-investment"; import { apiInvestmentCreateNews } from "@/service/api-client/api-investment";
@@ -80,7 +80,10 @@ export default function InvestmentAddNews() {
}; };
return ( return (
<ViewWrapper> <OS_Wrapper
enableKeyboardHandling
contentPaddingBottom={250}
>
<StackCustom gap={"xs"}> <StackCustom gap={"xs"}>
<InformationBox text="Pengunggahan foto ke aplikasi bersifat opsional dan tidak diwajibkan, Anda dapat menyimpan berita tanpa mengunggah foto." /> <InformationBox text="Pengunggahan foto ke aplikasi bersifat opsional dan tidak diwajibkan, Anda dapat menyimpan berita tanpa mengunggah foto." />
<LandscapeFrameUploaded image={image?.uri} /> <LandscapeFrameUploaded image={image?.uri} />
@@ -123,7 +126,6 @@ export default function InvestmentAddNews() {
Simpan Simpan
</ButtonCustom> </ButtonCustom>
</StackCustom> </StackCustom>
<Spacing /> </OS_Wrapper>
</ViewWrapper>
); );
} }

View File

@@ -2,10 +2,10 @@
import { import {
BaseBox, BaseBox,
Grid, Grid,
OS_Wrapper,
Spacing, Spacing,
StackCustom, StackCustom,
TextCustom, TextCustom,
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 { apiInvestmentGetInvoice } from "@/service/api-client/api-investment";
@@ -69,7 +69,7 @@ export default function InvestmentFailed() {
]; ];
return ( return (
<ViewWrapper> <OS_Wrapper>
<StackCustom> <StackCustom>
<BaseBox> <BaseBox>
<StackCustom> <StackCustom>
@@ -110,6 +110,6 @@ export default function InvestmentFailed() {
</StackCustom> </StackCustom>
</BaseBox> </BaseBox>
</StackCustom> </StackCustom>
</ViewWrapper> </OS_Wrapper>
); );
} }

View File

@@ -5,10 +5,10 @@ import {
ButtonCustom, ButtonCustom,
Divider, Divider,
Grid, Grid,
OS_Wrapper,
StackCustom, StackCustom,
TextCustom, TextCustom,
TextInputCustom, TextInputCustom,
ViewWrapper,
} from "@/components"; } from "@/components";
import { LOCAL_STORAGE_KEY } from "@/constants/local-storage-key"; import { LOCAL_STORAGE_KEY } from "@/constants/local-storage-key";
import { apiInvestmentGetOne } from "@/service/api-client/api-investment"; import { apiInvestmentGetOne } from "@/service/api-client/api-investment";
@@ -99,9 +99,12 @@ export default function InvestmentInvest() {
}; };
return ( return (
<> <OS_Wrapper
<ViewWrapper footerComponent={buttonSubmit()}> enableKeyboardHandling
<BaseBox> contentPaddingBottom={250}
footerComponent={buttonSubmit()}
>
<BaseBox>
<StackCustom gap={"xs"}> <StackCustom gap={"xs"}>
<Grid> <Grid>
<Grid.Col span={6}> <Grid.Col span={6}>
@@ -165,7 +168,6 @@ export default function InvestmentInvest() {
</Grid> </Grid>
</StackCustom> </StackCustom>
</BaseBox> </BaseBox>
</ViewWrapper> </OS_Wrapper>
</>
); );
} }

View File

@@ -1,11 +1,11 @@
import { BaseBox, StackCustom, TextCustom, ViewWrapper } from "@/components"; import { BaseBox, OS_Wrapper, StackCustom, TextCustom } from "@/components";
import MoneyTransferAnimation from "@/components/_ShareComponent/MoneyTransferAnimation"; import MoneyTransferAnimation from "@/components/_ShareComponent/MoneyTransferAnimation";
import { View } from "react-native"; import { View } from "react-native";
export default function InvestmentProcess() { export default function InvestmentProcess() {
return ( return (
<> <>
<ViewWrapper> <OS_Wrapper>
<BaseBox> <BaseBox>
<StackCustom> <StackCustom>
<TextCustom align="center" bold> <TextCustom align="center" bold>
@@ -35,7 +35,7 @@ export default function InvestmentProcess() {
</Grid.Col> </Grid.Col>
</Grid> </Grid>
</BaseBox> */} </BaseBox> */}
</ViewWrapper> </OS_Wrapper>
</> </>
); );
} }

View File

@@ -2,7 +2,7 @@ import {
BaseBox, BaseBox,
BoxButtonOnFooter, BoxButtonOnFooter,
ButtonCustom, ButtonCustom,
ViewWrapper, OS_Wrapper,
} from "@/components"; } from "@/components";
import { RadioCustom, RadioGroup } from "@/components/Radio/RadioCustom"; import { RadioCustom, RadioGroup } from "@/components/Radio/RadioCustom";
import { LOCAL_STORAGE_KEY } from "@/constants/local-storage-key"; import { LOCAL_STORAGE_KEY } from "@/constants/local-storage-key";
@@ -86,7 +86,7 @@ export default function InvestmentSelectBank() {
}; };
return ( return (
<ViewWrapper footerComponent={buttonSubmit()}> <OS_Wrapper footerComponent={buttonSubmit()}>
<RadioGroup value={select} onChange={setSelect}> <RadioGroup value={select} onChange={setSelect}>
{_.isEmpty(listBank) {_.isEmpty(listBank)
? [] ? []
@@ -96,6 +96,6 @@ export default function InvestmentSelectBank() {
</BaseBox> </BaseBox>
))} ))}
</RadioGroup> </RadioGroup>
</ViewWrapper> </OS_Wrapper>
); );
} }

View File

@@ -2,10 +2,10 @@
import { import {
BaseBox, BaseBox,
Grid, Grid,
OS_Wrapper,
Spacing, Spacing,
StackCustom, StackCustom,
TextCustom, TextCustom,
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 { apiInvestmentGetInvoice } from "@/service/api-client/api-investment";
@@ -69,7 +69,7 @@ export default function InvestmentSuccess() {
]; ];
return ( return (
<ViewWrapper> <OS_Wrapper>
<StackCustom> <StackCustom>
<BaseBox> <BaseBox>
<StackCustom> <StackCustom>
@@ -110,6 +110,6 @@ export default function InvestmentSuccess() {
</StackCustom> </StackCustom>
</BaseBox> </BaseBox>
</StackCustom> </StackCustom>
</ViewWrapper> </OS_Wrapper>
); );
} }

View File

@@ -4,7 +4,7 @@ import {
DotButton, DotButton,
DrawerCustom, DrawerCustom,
MenuDrawerDynamicGrid, MenuDrawerDynamicGrid,
ViewWrapper, OS_Wrapper,
} from "@/components"; } from "@/components";
import AppHeader from "@/components/_ShareComponent/AppHeader"; import AppHeader from "@/components/_ShareComponent/AppHeader";
import { IconDocument, IconEdit, IconNews } from "@/components/_Icon"; import { IconDocument, IconEdit, IconNews } from "@/components/_Icon";
@@ -123,14 +123,14 @@ export default function InvestmentDetailStatus() {
}} }}
/> />
<ViewWrapper> <OS_Wrapper>
<Invesment_DetailDataPublishSection <Invesment_DetailDataPublishSection
status={status as string} status={status as string}
data={data} data={data}
bottomSection={bottomSection} bottomSection={bottomSection}
buttonSection={buttonSection} buttonSection={buttonSection}
/> />
</ViewWrapper> </OS_Wrapper>
{/* ========= Draft Drawer ========= */} {/* ========= Draft Drawer ========= */}
<DrawerCustom <DrawerCustom

View File

@@ -7,10 +7,10 @@ import {
CenterCustom, CenterCustom,
InformationBox, InformationBox,
LoaderCustom, LoaderCustom,
OS_Wrapper,
Spacing, Spacing,
StackCustom, StackCustom,
TextCustom, TextCustom,
ViewWrapper,
} from "@/components"; } from "@/components";
import DIRECTORY_ID from "@/constants/directory-id"; import DIRECTORY_ID from "@/constants/directory-id";
import { import {
@@ -116,7 +116,7 @@ export default function InvestmentEditProspectus() {
</BoxButtonOnFooter> </BoxButtonOnFooter>
); );
return ( return (
<ViewWrapper footerComponent={!loadingGet && buttonFooter}> <OS_Wrapper footerComponent={!loadingGet && buttonFooter}>
<StackCustom gap={"xs"}> <StackCustom gap={"xs"}>
<InformationBox text="File prospektus wajib untuk diupload, agar calon investor paham dengan prospek investasi yang akan anda jalankan kedepan." /> <InformationBox text="File prospektus wajib untuk diupload, agar calon investor paham dengan prospek investasi yang akan anda jalankan kedepan." />
<Spacing /> <Spacing />
@@ -153,6 +153,6 @@ export default function InvestmentEditProspectus() {
Upload Upload
</ButtonCenteredOnly> </ButtonCenteredOnly>
</StackCustom> </StackCustom>
</ViewWrapper> </OS_Wrapper>
); );
} }

View File

@@ -6,7 +6,7 @@ import {
InformationBox, InformationBox,
LandscapeFrameUploaded, LandscapeFrameUploaded,
LoaderCustom, LoaderCustom,
NewWrapper, OS_Wrapper,
SelectCustom, SelectCustom,
Spacing, Spacing,
StackCustom, StackCustom,
@@ -199,7 +199,9 @@ export default function InvestmentEdit() {
}; };
return ( return (
<NewWrapper <OS_Wrapper
enableKeyboardHandling
contentPaddingBottom={250}
footerComponent={ footerComponent={
<BoxButtonOnFooter> <BoxButtonOnFooter>
<ButtonCustom isLoading={isLoading} onPress={handleSubmitUpdate}> <ButtonCustom isLoading={isLoading} onPress={handleSubmitUpdate}>
@@ -350,6 +352,6 @@ export default function InvestmentEdit() {
<Spacing /> <Spacing />
</StackCustom> </StackCustom>
</NewWrapper> </OS_Wrapper>
); );
} }

View File

@@ -4,7 +4,7 @@ import {
DotButton, DotButton,
DrawerCustom, DrawerCustom,
MenuDrawerDynamicGrid, MenuDrawerDynamicGrid,
ViewWrapper, OS_Wrapper,
} from "@/components"; } from "@/components";
import AppHeader from "@/components/_ShareComponent/AppHeader"; import AppHeader from "@/components/_ShareComponent/AppHeader";
import { IconDocument, IconEdit, IconNews } from "@/components/_Icon"; import { IconDocument, IconEdit, IconNews } from "@/components/_Icon";
@@ -122,14 +122,14 @@ export default function InvestmentDetail() {
}} }}
/> />
<ViewWrapper> <OS_Wrapper>
<Invesment_DetailDataPublishSection <Invesment_DetailDataPublishSection
status={"publish"} status={"publish"}
data={data} data={data}
bottomSection={bottomSection} bottomSection={bottomSection}
buttonSection={buttonSection} buttonSection={buttonSection}
/> />
</ViewWrapper> </OS_Wrapper>
{/* ========= Draft Drawer ========= */} {/* ========= Draft Drawer ========= */}
<DrawerCustom <DrawerCustom

View File

@@ -6,7 +6,7 @@ import {
CenterCustom, CenterCustom,
InformationBox, InformationBox,
LandscapeFrameUploaded, LandscapeFrameUploaded,
NewWrapper, OS_Wrapper,
SelectCustom, SelectCustom,
Spacing, Spacing,
StackCustom, StackCustom,
@@ -185,7 +185,9 @@ export default function InvestmentCreate() {
// const [coba, setCoba] = useState(""); // const [coba, setCoba] = useState("");
return ( return (
<NewWrapper <OS_Wrapper
enableKeyboardHandling
contentPaddingBottom={250}
footerComponent={ footerComponent={
<BoxButtonOnFooter> <BoxButtonOnFooter>
<ButtonCustom <ButtonCustom
@@ -373,7 +375,6 @@ export default function InvestmentCreate() {
<Spacing /> <Spacing />
</StackCustom> </StackCustom>
{/* <Spacing height={50} /> */} </OS_Wrapper>
</NewWrapper>
); );
} }

View File

@@ -1,7 +1,6 @@
/* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable react-hooks/exhaustive-deps */
import { TextCustom } from "@/components"; import { TextCustom, OS_Wrapper } from "@/components";
import NewWrapper from "@/components/_ShareComponent/NewWrapper"; import { PAGINATION_DEFAULT_TAKE, PADDING_INLINE } from "@/constants/constans-value";
import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value";
import { createPaginationComponents } from "@/helpers/paginationHelpers"; import { createPaginationComponents } from "@/helpers/paginationHelpers";
import { usePagination } from "@/hooks/use-pagination"; import { usePagination } from "@/hooks/use-pagination";
import Investment_BoxDetailDocument from "@/screens/Invesment/Document/RecapBoxDetail"; import Investment_BoxDetailDocument from "@/screens/Invesment/Document/RecapBoxDetail";
@@ -58,8 +57,9 @@ export default function Investment_ScreenListOfDocument() {
); );
return ( return (
<NewWrapper <OS_Wrapper
hideFooter hideFooter
contentPadding={PADDING_INLINE}
listData={pagination.listData} listData={pagination.listData}
renderItem={renderDocumentItem} renderItem={renderDocumentItem}
refreshControl={ refreshControl={

View File

@@ -4,13 +4,13 @@ import {
BackButton, BackButton,
DotButton, DotButton,
DrawerCustom, DrawerCustom,
MenuDrawerDynamicGrid MenuDrawerDynamicGrid,
OS_Wrapper,
} from "@/components"; } from "@/components";
import AppHeader from "@/components/_ShareComponent/AppHeader"; import AppHeader from "@/components/_ShareComponent/AppHeader";
import { IconEdit } from "@/components/_Icon"; import { IconEdit } from "@/components/_Icon";
import NewWrapper from "@/components/_ShareComponent/NewWrapper";
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_SMALL, PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value"; import { ICON_SIZE_SMALL, PAGINATION_DEFAULT_TAKE, PADDING_INLINE } from "@/constants/constans-value";
import { createPaginationComponents } from "@/helpers/paginationHelpers"; import { createPaginationComponents } from "@/helpers/paginationHelpers";
import { usePagination } from "@/hooks/use-pagination"; import { usePagination } from "@/hooks/use-pagination";
import Investment_BoxDetailDocument from "@/screens/Invesment/Document/RecapBoxDetail"; import Investment_BoxDetailDocument from "@/screens/Invesment/Document/RecapBoxDetail";
@@ -143,8 +143,9 @@ export default function Investment_ScreenRecapOfDocument() {
}} }}
/> />
<NewWrapper <OS_Wrapper
hideFooter hideFooter
contentPadding={PADDING_INLINE}
listData={pagination.listData} listData={pagination.listData}
renderItem={renderDocumentItem} renderItem={renderDocumentItem}
refreshControl={ refreshControl={

View File

@@ -5,11 +5,12 @@ import {
DrawerCustom, DrawerCustom,
LoaderCustom, LoaderCustom,
MenuDrawerDynamicGrid, MenuDrawerDynamicGrid,
OS_Wrapper,
TextCustom, TextCustom,
} from "@/components"; } from "@/components";
import AppHeader from "@/components/_ShareComponent/AppHeader"; import AppHeader from "@/components/_ShareComponent/AppHeader";
import { IconPlus } from "@/components/_Icon"; import { IconPlus } from "@/components/_Icon";
import NewWrapper from "@/components/_ShareComponent/NewWrapper"; import { PADDING_INLINE } from "@/constants/constans-value";
import { usePagination } from "@/hooks/use-pagination"; import { usePagination } from "@/hooks/use-pagination";
import { apiInvestmentGetNews } from "@/service/api-client/api-investment"; import { apiInvestmentGetNews } from "@/service/api-client/api-investment";
import { router, Stack, useFocusEffect } from "expo-router"; import { router, Stack, useFocusEffect } from "expo-router";
@@ -75,8 +76,9 @@ export default function Investment_ScreenListOfNews({
}} }}
/> />
<NewWrapper <OS_Wrapper
hideFooter hideFooter
contentPadding={PADDING_INLINE}
listData={pagination.listData} listData={pagination.listData}
renderItem={renderItem} renderItem={renderItem}
onEndReached={pagination.loadMore} onEndReached={pagination.loadMore}

View File

@@ -6,19 +6,19 @@ import {
DrawerCustom, DrawerCustom,
LoaderCustom, LoaderCustom,
MenuDrawerDynamicGrid, MenuDrawerDynamicGrid,
OS_Wrapper,
Spacing, Spacing,
TextCustom, TextCustom,
} from "@/components"; } from "@/components";
import AppHeader from "@/components/_ShareComponent/AppHeader"; import AppHeader from "@/components/_ShareComponent/AppHeader";
import { IconPlus } from "@/components/_Icon"; import { IconPlus } from "@/components/_Icon";
import NewWrapper from "@/components/_ShareComponent/NewWrapper"; import { PAGINATION_DEFAULT_TAKE, PADDING_INLINE } from "@/constants/constans-value";
import { createPaginationComponents } from "@/helpers/paginationHelpers";
import { usePagination } from "@/hooks/use-pagination"; import { usePagination } from "@/hooks/use-pagination";
import { apiInvestmentGetNews } from "@/service/api-client/api-investment"; import { apiInvestmentGetNews } from "@/service/api-client/api-investment";
import { router, Stack, useFocusEffect } from "expo-router"; import { router, Stack, useFocusEffect } from "expo-router";
import { useCallback, useState } from "react"; import { useCallback, useState } from "react";
import { RefreshControl } from "react-native"; import { RefreshControl } from "react-native";
import { createPaginationComponents } from "@/helpers/paginationHelpers";
import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value";
import Investment_BoxNews from "./BoxNews"; import Investment_BoxNews from "./BoxNews";
interface InvestmentRecapOfNewsProps { interface InvestmentRecapOfNewsProps {
@@ -76,8 +76,9 @@ export default function Investment_ScreenRecapOfNews({
), ),
}} }}
/> />
<NewWrapper <OS_Wrapper
hideFooter hideFooter
contentPadding={PADDING_INLINE}
listData={pagination.listData} listData={pagination.listData}
renderItem={renderItem} renderItem={renderItem}
onEndReached={pagination.loadMore} onEndReached={pagination.loadMore}

View File

@@ -1,8 +1,9 @@
import { import {
FloatingButton, FloatingButton,
OS_Wrapper,
TextCustom, TextCustom,
} from "@/components"; } from "@/components";
import NewWrapper from "@/components/_ShareComponent/NewWrapper"; import { PADDING_INLINE } from "@/constants/constans-value";
import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value"; import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value";
import { createPaginationComponents } from "@/helpers/paginationHelpers"; import { createPaginationComponents } from "@/helpers/paginationHelpers";
import { usePagination } from "@/hooks/use-pagination"; import { usePagination } from "@/hooks/use-pagination";
@@ -46,7 +47,8 @@ export default function Investment_ScreenBursa() {
); );
return ( return (
<NewWrapper <OS_Wrapper
contentPadding={PADDING_INLINE}
listData={pagination.listData} listData={pagination.listData}
renderItem={renderInvestmentItem} renderItem={renderInvestmentItem}
refreshControl={ refreshControl={

View File

@@ -3,12 +3,12 @@ import {
AvatarUsernameAndOtherComponent, AvatarUsernameAndOtherComponent,
BoxWithHeaderSection, BoxWithHeaderSection,
CenterCustom, CenterCustom,
OS_Wrapper,
Spacing, Spacing,
StackCustom, StackCustom,
TextCustom, TextCustom,
} from "@/components"; } from "@/components";
import NewWrapper from "@/components/_ShareComponent/NewWrapper"; import { PAGINATION_DEFAULT_TAKE, PADDING_INLINE } from "@/constants/constans-value";
import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value";
import { createPaginationComponents } from "@/helpers/paginationHelpers"; import { createPaginationComponents } from "@/helpers/paginationHelpers";
import { usePagination } from "@/hooks/use-pagination"; import { usePagination } from "@/hooks/use-pagination";
import { apiInvestmentGetInvestorById } from "@/service/api-client/api-investment"; import { apiInvestmentGetInvestorById } from "@/service/api-client/api-investment";
@@ -66,8 +66,9 @@ export default function Investment_ScreenInvestor({
}); });
return ( return (
<NewWrapper <OS_Wrapper
hideFooter hideFooter
contentPadding={PADDING_INLINE}
listData={pagination.listData} listData={pagination.listData}
renderItem={renderItem} renderItem={renderItem}
onEndReached={pagination.loadMore} onEndReached={pagination.loadMore}

View File

@@ -5,10 +5,10 @@ import {
ButtonCustom, ButtonCustom,
Grid, Grid,
InformationBox, InformationBox,
OS_Wrapper,
Spacing, Spacing,
StackCustom, StackCustom,
TextCustom, TextCustom,
ViewWrapper,
} from "@/components"; } from "@/components";
import CopyButton from "@/components/Button/CoyButton"; import CopyButton from "@/components/Button/CoyButton";
import { MainColor } from "@/constants/color-palet"; import { MainColor } from "@/constants/color-palet";
@@ -94,7 +94,7 @@ export default function Investment_ScreenInvoice() {
return ( return (
<> <>
<ViewWrapper> <OS_Wrapper>
<StackCustom> <StackCustom>
<InformationBox text="Mohon transfer ke rekening dibawah" /> <InformationBox text="Mohon transfer ke rekening dibawah" />
<BaseBox> <BaseBox>
@@ -224,7 +224,7 @@ export default function Investment_ScreenInvoice() {
</ButtonCustom> </ButtonCustom>
</StackCustom> </StackCustom>
<Spacing /> <Spacing />
</ViewWrapper> </OS_Wrapper>
</> </>
); );
} }

View File

@@ -1,11 +1,12 @@
/* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable react-hooks/exhaustive-deps */
import { import {
BaseBox, BaseBox,
OS_Wrapper,
ProgressCustom, ProgressCustom,
StackCustom, StackCustom,
TextCustom TextCustom
} from "@/components"; } from "@/components";
import NewWrapper from "@/components/_ShareComponent/NewWrapper"; import { PADDING_INLINE } from "@/constants/constans-value";
import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value"; import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value";
import { createPaginationComponents } from "@/helpers/paginationHelpers"; import { createPaginationComponents } from "@/helpers/paginationHelpers";
import { useAuth } from "@/hooks/use-auth"; import { useAuth } from "@/hooks/use-auth";
@@ -73,7 +74,8 @@ export default function Investment_ScreenMyHolding() {
}); });
return ( return (
<NewWrapper <OS_Wrapper
contentPadding={PADDING_INLINE}
listData={pagination.listData} listData={pagination.listData}
renderItem={renderItem} renderItem={renderItem}
onEndReached={pagination.loadMore} onEndReached={pagination.loadMore}

View File

@@ -1,6 +1,6 @@
/* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable react-hooks/exhaustive-deps */
import { ScrollableCustom, TextCustom } from "@/components"; import { OS_Wrapper, ScrollableCustom, TextCustom } from "@/components";
import NewWrapper from "@/components/_ShareComponent/NewWrapper"; import { PADDING_INLINE } from "@/constants/constans-value";
import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value"; import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value";
import { createPaginationComponents } from "@/helpers/paginationHelpers"; import { createPaginationComponents } from "@/helpers/paginationHelpers";
import { useAuth } from "@/hooks/use-auth"; import { useAuth } from "@/hooks/use-auth";
@@ -83,7 +83,8 @@ export default function Investment_ScreenPortofolio() {
); );
return ( return (
<NewWrapper <OS_Wrapper
contentPadding={PADDING_INLINE}
hideFooter hideFooter
headerComponent={tabsComponent} headerComponent={tabsComponent}
listData={pagination.listData} listData={pagination.listData}

View File

@@ -3,12 +3,13 @@ import {
BadgeCustom, BadgeCustom,
BaseBox, BaseBox,
Grid, Grid,
OS_Wrapper,
Spacing, Spacing,
StackCustom, StackCustom,
TextCustom, TextCustom,
} from "@/components"; } from "@/components";
import NewWrapper from "@/components/_ShareComponent/NewWrapper";
import NoDataText from "@/components/_ShareComponent/NoDataText"; import NoDataText from "@/components/_ShareComponent/NoDataText";
import { PADDING_INLINE } from "@/constants/constans-value";
import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value"; import { PAGINATION_DEFAULT_TAKE } from "@/constants/constans-value";
import { createPaginationComponents } from "@/helpers/paginationHelpers"; import { createPaginationComponents } from "@/helpers/paginationHelpers";
import { useAuth } from "@/hooks/use-auth"; import { useAuth } from "@/hooks/use-auth";
@@ -128,7 +129,8 @@ export default function Investment_ScreenTransaction() {
); );
return ( return (
<NewWrapper <OS_Wrapper
contentPadding={PADDING_INLINE}
hideFooter hideFooter
listData={pagination.listData} listData={pagination.listData}
renderItem={renderTransactionItem} renderItem={renderTransactionItem}

View File

@@ -280,54 +280,60 @@ import { OS_Wrapper } from "@/components";
--- ---
## User Phase 9: Investment Screens - PENDING ## User Phase 9: Investment Screens - COMPLETED (2026-04-13)
**Files to migrate: 24** **Files migrated: 24**
#### Investment Tabs Screens (OS_Wrapper - tabs dengan contentPadding={PADDING_INLINE}): #### Investment Tabs Screens (OS_Wrapper - tabs dengan contentPadding={PADDING_INLINE}):
- [ ] `screens/Invesment/ScreenBursa.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (tabs list - index) - `screens/Invesment/ScreenBursa.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (tabs list - index)
- [ ] `screens/Invesment/ScreenMyHolding.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (tabs list - my-holding) - `screens/Invesment/ScreenMyHolding.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (tabs list - my-holding)
- [ ] `screens/Invesment/ScreenPortofolio.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (tabs list - portofolio) - `screens/Invesment/ScreenPortofolio.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (tabs list - portofolio)
- [ ] `screens/Invesment/ScreenTransaction.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (tabs list - transaction) - `screens/Invesment/ScreenTransaction.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (tabs list - transaction)
#### Investment List/Document Screens (OS_Wrapper dengan contentPadding={PADDING_INLINE}): #### Investment List/Document Screens (OS_Wrapper dengan contentPadding={PADDING_INLINE}):
- [ ] `screens/Invesment/ScreenInvestor.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (investor list) - `screens/Invesment/ScreenInvestor.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (investor list)
- [ ] `screens/Invesment/Document/ScreenListDocument.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (document list) - `screens/Invesment/Document/ScreenListDocument.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (document list)
- [ ] `screens/Invesment/Document/ScreenRecapOfDocument.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (document recap) - `screens/Invesment/Document/ScreenRecapOfDocument.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (document recap)
- [ ] `screens/Invesment/News/ScreenListOfNews.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (news list) - `screens/Invesment/News/ScreenListOfNews.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (news list)
- [ ] `screens/Invesment/News/ScreenRecapOfNews.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (news recap) - `screens/Invesment/News/ScreenRecapOfNews.tsx` - NewWrapper → OS_Wrapper + `contentPadding={PADDING_INLINE}` (news recap)
#### Investment Detail Screens (OS_Wrapper static): #### Investment Detail Screens (OS_Wrapper static):
- [ ] `app/(application)/(user)/investment/[id]/index.tsx` - ViewWrapper → OS_Wrapper (detail main) - `app/(application)/(user)/investment/[id]/index.tsx` - ViewWrapper → OS_Wrapper (detail main)
- [ ] `app/(application)/(user)/investment/[id]/[status]/detail.tsx` - ViewWrapper → OS_Wrapper (detail status) - `app/(application)/(user)/investment/[id]/[status]/detail.tsx` - ViewWrapper → OS_Wrapper (detail status)
- [ ] `app/(application)/(user)/investment/[id]/(my-holding)/[id].tsx` - ViewWrapper → OS_Wrapper (holding detail) - `app/(application)/(user)/investment/[id]/(my-holding)/[id].tsx` - ViewWrapper → OS_Wrapper (holding detail)
- [ ] `app/(application)/(user)/investment/[id]/edit-prospectus.tsx` - ViewWrapper → OS_Wrapper (file upload) - `app/(application)/(user)/investment/[id]/edit-prospectus.tsx` - ViewWrapper → OS_Wrapper (file upload)
- [ ] `app/(application)/(user)/investment/[id]/(news)/[news]/index.tsx` - ViewWrapper → OS_Wrapper (news detail) - `app/(application)/(user)/investment/[id]/(news)/[news]/index.tsx` - ViewWrapper → OS_Wrapper (news detail)
#### Investment Form Screens (OS_Wrapper with enableKeyboardHandling): #### Investment Form Screens (OS_Wrapper with enableKeyboardHandling):
- [ ] `app/(application)/(user)/investment/create.tsx` - NewWrapper → OS_Wrapper + `enableKeyboardHandling` + `contentPaddingBottom={250}` - `app/(application)/(user)/investment/create.tsx` - NewWrapper → OS_Wrapper + `enableKeyboardHandling` + `contentPaddingBottom={250}`
- [ ] `app/(application)/(user)/investment/[id]/edit.tsx` - NewWrapper → OS_Wrapper + `enableKeyboardHandling` + `contentPaddingBottom={250}` - `app/(application)/(user)/investment/[id]/edit.tsx` - NewWrapper → OS_Wrapper + `enableKeyboardHandling` + `contentPaddingBottom={250}`
- [ ] `app/(application)/(user)/investment/[id]/(document)/add-document.tsx` - ViewWrapper → OS_Wrapper + `enableKeyboardHandling` + `contentPaddingBottom={250}` - `app/(application)/(user)/investment/[id]/(document)/add-document.tsx` - ViewWrapper → OS_Wrapper + `enableKeyboardHandling` + `contentPaddingBottom={250}`
- [ ] `app/(application)/(user)/investment/[id]/(document)/edit-document.tsx` - ViewWrapper → OS_Wrapper + `enableKeyboardHandling` + `contentPaddingBottom={250}` - `app/(application)/(user)/investment/[id]/(document)/edit-document.tsx` - ViewWrapper → OS_Wrapper + `enableKeyboardHandling` + `contentPaddingBottom={250}`
- [ ] `app/(application)/(user)/investment/[id]/(news)/add-news.tsx` - ViewWrapper → OS_Wrapper + `enableKeyboardHandling` + `contentPaddingBottom={250}` - `app/(application)/(user)/investment/[id]/(news)/add-news.tsx` - ViewWrapper → OS_Wrapper + `enableKeyboardHandling` + `contentPaddingBottom={250}`
- [ ] `app/(application)/(user)/investment/[id]/(transaction-flow)/index.tsx` - ViewWrapper → OS_Wrapper + `enableKeyboardHandling` + `contentPaddingBottom={250}` - `app/(application)/(user)/investment/[id]/(transaction-flow)/index.tsx` - ViewWrapper → OS_Wrapper + `enableKeyboardHandling` + `contentPaddingBottom={250}`
#### Investment Transaction Flow (OS_Wrapper static/no keyboard): #### Investment Transaction Flow (OS_Wrapper static/no keyboard):
- [ ] `screens/Invesment/ScreenInvoice.tsx` - ViewWrapper → OS_Wrapper (invoice display) - `screens/Invesment/ScreenInvoice.tsx` - ViewWrapper → OS_Wrapper (invoice display)
- [ ] `app/(application)/(user)/investment/[id]/(transaction-flow)/process.tsx` - ViewWrapper → OS_Wrapper (status page) - `app/(application)/(user)/investment/[id]/(transaction-flow)/process.tsx` - ViewWrapper → OS_Wrapper (status page)
- [ ] `app/(application)/(user)/investment/[id]/(transaction-flow)/select-bank.tsx` - ViewWrapper → OS_Wrapper (bank selection) - `app/(application)/(user)/investment/[id]/(transaction-flow)/select-bank.tsx` - ViewWrapper → OS_Wrapper (bank selection)
- [ ] `app/(application)/(user)/investment/[id]/(transaction-flow)/failed.tsx` - ViewWrapper → OS_Wrapper (status failed) - `app/(application)/(user)/investment/[id]/(transaction-flow)/failed.tsx` - ViewWrapper → OS_Wrapper (status failed)
- [ ] `app/(application)/(user)/investment/[id]/(transaction-flow)/success.tsx` - ViewWrapper → OS_Wrapper (status success) - `app/(application)/(user)/investment/[id]/(transaction-flow)/success.tsx` - ViewWrapper → OS_Wrapper (status success)
#### Investment Tabs Layout Height Fix: #### Investment Tabs Layout Height Fix:
- [ ] `app/(application)/(user)/investment/(tabs)/_layout.tsx` - Hardcode → `OS_IOS_HEIGHT` / `OS_ANDROID_HEIGHT` - `app/(application)/(user)/investment/(tabs)/_layout.tsx` - Hardcode → `OS_IOS_HEIGHT` / `OS_ANDROID_HEIGHT`
**Testing Status:** **Testing Status:**
- TypeScript: Pending - TypeScript: No errors
- ⏳ Build: Pending - ⏳ Build: Pending
- ⏳ iOS Testing: Pending - ⏳ iOS Testing: Pending
- ⏳ Android Testing: Pending - ⏳ Android Testing: Pending
#### ⚠️ Known Issues - Investment Upload:
- **Issue:** Error saat upload gambar di `investment/create.tsx`
- **Error Message:** `url >> http://192.168.1.112:3000/api/mobile/file` + `[ERROR] [AxiosError: Request failed with status code 500]`
- **Status:** ❌ Belum diperbaiki - akan diperbaiki besok
- **Note Penting:** Fitur Investment **belum sepenuhnya rampung** - masih ada issue upload file yang perlu diinvestigasi lebih lanjut. Kemungkinan masalah di server upload service atau environment development. Production saat ini masih aman.
--- ---
# 🔴 ADMIN PHASES (Admin-Facing Screens) # 🔴 ADMIN PHASES (Admin-Facing Screens)
@@ -475,10 +481,10 @@ import { OS_Wrapper } from "@/components";
| User Phase 6 (Event) | 16 | 16 | ⏳ Pending | ✅ Complete | | User Phase 6 (Event) | 16 | 16 | ⏳ Pending | ✅ Complete |
| User Phase 7 (Voting) | 11 | 11 | ✅ No errors | ✅ Complete | | User Phase 7 (Voting) | 11 | 11 | ✅ No errors | ✅ Complete |
| User Phase 8 (Donation + Others) | 31 | 31 | ✅ No errors | ✅ Complete | | User Phase 8 (Donation + Others) | 31 | 31 | ✅ No errors | ✅ Complete |
| User Phase 9 (Investment) | 24 | 0 | 0 | ⏳ Pending | | User Phase 9 (Investment) | 24 | 24 | ✅ No errors | ✅ Complete |
| User Phase 10 (Collaboration) | ~3 | 0 | 0 | ⏳ Pending | | User Phase 10 (Collaboration) | ~3 | 0 | 0 | ⏳ Pending |
| User Phase 11 (Others) | ~3 | 0 | 0 | ⏳ Pending | | User Phase 11 (Others) | ~3 | 0 | 0 | ⏳ Pending |
| **User Total** | **~132** | **102** | **10** | **~77% Complete** | | **User Total** | **~132** | **126** | **10** | **~95% Complete** |
### Admin Phases: ### Admin Phases:
| Phase | Total Files | Migrated | Testing | Status | | Phase | Total Files | Migrated | Testing | Status |
@@ -497,9 +503,9 @@ import { OS_Wrapper } from "@/components";
### Grand Total: ### Grand Total:
| Category | Total Files | Migrated | Status | | Category | Total Files | Migrated | Status |
|----------|-------------|----------|--------| |----------|-------------|----------|--------|
| **User Screens** | ~132 | 102 | ~77% Complete | | **User Screens** | ~132 | 126 | ~95% Complete |
| **Admin Screens** | ~31 | 2 | ~6% Complete | | **Admin Screens** | ~31 | 2 | ~6% Complete |
| **GRAND TOTAL** | **~163** | **104** | **~64% Complete** | | **GRAND TOTAL** | **~163** | **128** | **~79% Complete** |
## 🔄 Rollback Plan ## 🔄 Rollback Plan
@@ -514,5 +520,6 @@ Jika ada issue yang tidak bisa di-fix dalam 1 jam:
**Co-authored-by**: Qwen-Coder <qwen-coder@alibabacloud.com> **Co-authored-by**: Qwen-Coder <qwen-coder@alibabacloud.com>
**Created**: 2026-04-06 **Created**: 2026-04-06
**Last Updated**: 2026-04-13 **Last Updated**: 2026-04-13
**Status**: User Phase 1-8 Complete ✅ | Admin Phase 9 Complete ✅ (104 files migrated) **Status**: User Phase 1-9 Complete ✅ (with known issues) | Admin Phase 9 Complete ✅ (128 files migrated)
**Next**: User Phase 9 - Investment Screens (24 files) **Next**: User Phase 10-11 (~6 files) OR Admin Phase 1-3 (HIGH Priority, ~9 files)
**TODO Tomorrow**: Fix Investment upload error (status 500 on image upload)