feat: implement pagination and NewWrapper on donation and investment screens
- Implement pagination on investment screens (ScreenMyHolding, ScreenInvestor, ScreenRecapOfNews, ScreenListOfNews) - Implement pagination on donation screens (ScreenStatus) - Update API functions to support pagination with page parameter (apiInvestmentGetAll, apiInvestmentGetInvestorById, apiInvestmentGetNews, apiDonationGetByStatus) - Replace ViewWrapper with NewWrapper for better UI experience - Update app directory files to use new modular components from screens directory - Add pull-to-refresh and infinite scroll functionality - Improve performance by loading data incrementally - Apply NewWrapper to donation create and create-story screens Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@@ -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 Donasi_BoxStatus from "@/screens/Donation/BoxStatus";
|
||||
import { apiDonationGetByStatus } from "@/service/api-client/api-donation";
|
||||
import { useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||
import _ from "lodash";
|
||||
import { useCallback, useState } from "react";
|
||||
import Donation_ScreenStatus from "@/screens/Donation/ScreenStatus";
|
||||
import { useLocalSearchParams } from "expo-router";
|
||||
|
||||
export default function DonationStatus() {
|
||||
const { user } = useAuth();
|
||||
const { status } = useLocalSearchParams<{ status?: string }>();
|
||||
|
||||
const [activeCategory, setActiveCategory] = useState<string | null>(
|
||||
status || "publish",
|
||||
);
|
||||
const [listData, setListData] = useState<any[] | null>(null);
|
||||
const [loadList, setLoadList] = useState(false);
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
onLoadList();
|
||||
}, [activeCategory]),
|
||||
);
|
||||
|
||||
const onLoadList = async () => {
|
||||
try {
|
||||
setLoadList(true);
|
||||
const response = await apiDonationGetByStatus({
|
||||
authorId: user?.id as string,
|
||||
status: activeCategory as string,
|
||||
});
|
||||
|
||||
setListData(response.data);
|
||||
} catch (error) {
|
||||
console.log("[ERROR]", error);
|
||||
setListData(null);
|
||||
} finally {
|
||||
setLoadList(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 hideFooter headerComponent={scrollComponent}>
|
||||
{loadList ? (
|
||||
<LoaderCustom />
|
||||
) : _.isEmpty(listData) ? (
|
||||
<TextCustom align="center">Tidak ada data {activeCategory}</TextCustom>
|
||||
) : (
|
||||
listData?.map((item: any, index: number) => (
|
||||
<Donasi_BoxStatus
|
||||
key={index}
|
||||
data={item}
|
||||
status={activeCategory as string}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
</ViewWrapper>
|
||||
<Donation_ScreenStatus initialStatus={status || "publish"} />
|
||||
);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ export default function DonasiDetailStatus() {
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
onLoadData();
|
||||
}, [id])
|
||||
}, [id]),
|
||||
);
|
||||
|
||||
const onLoadData = async () => {
|
||||
@@ -99,6 +99,7 @@ export default function DonasiDetailStatus() {
|
||||
sisaHari={value.sisa}
|
||||
reminder={value.reminder}
|
||||
data={data}
|
||||
showSisaHari={status === "publish" ? true : false}
|
||||
bottomSection={
|
||||
status === "publish" && (
|
||||
<Donation_ProgressSection
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import {
|
||||
BoxButtonOnFooter,
|
||||
ButtonCenteredOnly,
|
||||
ButtonCustom,
|
||||
InformationBox,
|
||||
LandscapeFrameUploaded,
|
||||
LoaderCustom,
|
||||
NewWrapper,
|
||||
SelectCustom,
|
||||
Spacing,
|
||||
StackCustom,
|
||||
@@ -60,7 +62,7 @@ export default function DonationEdit() {
|
||||
useCallback(() => {
|
||||
onLoadData();
|
||||
onLoadList();
|
||||
}, [id])
|
||||
}, [id]),
|
||||
);
|
||||
|
||||
const onLoadData = async () => {
|
||||
@@ -79,7 +81,6 @@ export default function DonationEdit() {
|
||||
imageId: response.data.imageId,
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log("[ERROR]", error);
|
||||
}
|
||||
@@ -182,7 +183,21 @@ export default function DonationEdit() {
|
||||
};
|
||||
|
||||
return (
|
||||
<ViewWrapper>
|
||||
<NewWrapper
|
||||
hideFooter
|
||||
footerComponent={
|
||||
<BoxButtonOnFooter>
|
||||
<ButtonCustom
|
||||
isLoading={isLoading}
|
||||
onPress={() => {
|
||||
handlerSubmitUpdate();
|
||||
}}
|
||||
>
|
||||
Update
|
||||
</ButtonCustom>
|
||||
</BoxButtonOnFooter>
|
||||
}
|
||||
>
|
||||
<InformationBox text="Lengkapi semua data di bawah untuk selanjutnya mengisi cerita penggalangan dana." />
|
||||
{!data || loadList ? (
|
||||
<LoaderCustom />
|
||||
@@ -260,17 +275,9 @@ export default function DonationEdit() {
|
||||
/>
|
||||
|
||||
<Spacing />
|
||||
<ButtonCustom
|
||||
isLoading={isLoading}
|
||||
onPress={() => {
|
||||
handlerSubmitUpdate();
|
||||
}}
|
||||
>
|
||||
Update
|
||||
</ButtonCustom>
|
||||
</StackCustom>
|
||||
)}
|
||||
<Spacing />
|
||||
</ViewWrapper>
|
||||
</NewWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import {
|
||||
BoxButtonOnFooter,
|
||||
ButtonCenteredOnly,
|
||||
ButtonCustom,
|
||||
InformationBox,
|
||||
@@ -8,8 +9,8 @@ import {
|
||||
StackCustom,
|
||||
TextAreaCustom,
|
||||
TextInputCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
import NewWrapper from "@/components/_ShareComponent/NewWrapper";
|
||||
import DIRECTORY_ID from "@/constants/directory-id";
|
||||
import { useAuth } from "@/hooks/use-auth";
|
||||
import {
|
||||
@@ -112,7 +113,23 @@ export default function DonationCreateStory() {
|
||||
};
|
||||
|
||||
return (
|
||||
<ViewWrapper>
|
||||
<NewWrapper
|
||||
hideFooter
|
||||
footerComponent={
|
||||
<>
|
||||
<BoxButtonOnFooter>
|
||||
<ButtonCustom
|
||||
isLoading={isLoading}
|
||||
onPress={() => {
|
||||
handlerSubmit();
|
||||
}}
|
||||
>
|
||||
Simpan
|
||||
</ButtonCustom>
|
||||
</BoxButtonOnFooter>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<StackCustom gap={"xs"}>
|
||||
<InformationBox text="Cerita Anda adalah kunci untuk menginspirasi kebaikan. Jelaskan dengan jujur dan jelas tujuan penggalangan dana ini agar calon donatur memahami dampak positif yang dapat mereka wujudkan melalui kontribusi mereka." />
|
||||
<TextAreaCustom
|
||||
@@ -166,18 +183,8 @@ export default function DonationCreateStory() {
|
||||
value={data.rekening}
|
||||
onChangeText={(value) => setData({ ...data, rekening: value })}
|
||||
/>
|
||||
|
||||
<Spacing />
|
||||
<ButtonCustom
|
||||
isLoading={isLoading}
|
||||
onPress={() => {
|
||||
handlerSubmit();
|
||||
}}
|
||||
>
|
||||
Simpan
|
||||
</ButtonCustom>
|
||||
</StackCustom>
|
||||
<Spacing />
|
||||
</ViewWrapper>
|
||||
</NewWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
BoxButtonOnFooter,
|
||||
ButtonCenteredOnly,
|
||||
ButtonCustom,
|
||||
InformationBox,
|
||||
@@ -8,8 +9,8 @@ import {
|
||||
Spacing,
|
||||
StackCustom,
|
||||
TextInputCustom,
|
||||
ViewWrapper,
|
||||
} from "@/components";
|
||||
import NewWrapper from "@/components/_ShareComponent/NewWrapper";
|
||||
import DIRECTORY_ID from "@/constants/directory-id";
|
||||
import { apiDonationCreate } from "@/service/api-client/api-donation";
|
||||
import { apiMasterDonation } from "@/service/api-client/api-master";
|
||||
@@ -43,7 +44,7 @@ export default function DonationCreate() {
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
onLoadList();
|
||||
}, [])
|
||||
}, []),
|
||||
);
|
||||
|
||||
const onLoadList = async () => {
|
||||
@@ -125,7 +126,24 @@ export default function DonationCreate() {
|
||||
};
|
||||
|
||||
return (
|
||||
<ViewWrapper>
|
||||
<NewWrapper
|
||||
hideFooter
|
||||
footerComponent={
|
||||
<>
|
||||
<BoxButtonOnFooter>
|
||||
<ButtonCustom
|
||||
isLoading={isLoading}
|
||||
onPress={() => {
|
||||
handlerSubmit();
|
||||
// router.push(`/donation/create-story?id=${"dasdsadsa"}`);
|
||||
}}
|
||||
>
|
||||
Selanjutnya
|
||||
</ButtonCustom>
|
||||
</BoxButtonOnFooter>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<StackCustom gap={"xs"}>
|
||||
<InformationBox text="Lengkapi semua data di bawah untuk selanjutnya mengisi cerita penggalangan dana." />
|
||||
|
||||
@@ -201,20 +219,8 @@ export default function DonationCreate() {
|
||||
onChange={(value: any) => setData({ ...data, durasiId: value })}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Spacing />
|
||||
<ButtonCustom
|
||||
isLoading={isLoading}
|
||||
onPress={() => {
|
||||
handlerSubmit();
|
||||
// router.push(`/donation/create-story?id=${"dasdsadsa"}`);
|
||||
}}
|
||||
>
|
||||
Selanjutnya
|
||||
</ButtonCustom>
|
||||
<Spacing />
|
||||
</StackCustom>
|
||||
<Spacing />
|
||||
</ViewWrapper>
|
||||
</NewWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -73,7 +73,6 @@ export default function InvestmentDetailStatus() {
|
||||
updateCountDown();
|
||||
}, [data]);
|
||||
|
||||
console.log("[DATA DETAIL]", JSON.stringify(data, null, 2));
|
||||
|
||||
const updateCountDown = () => {
|
||||
const countDown = countDownAndCondition({
|
||||
|
||||
@@ -72,7 +72,6 @@ export default function InvestmentDetail() {
|
||||
updateCountDown();
|
||||
}, [data]);
|
||||
|
||||
console.log("[DATA DETAIL]", JSON.stringify(data, null, 2));
|
||||
|
||||
const updateCountDown = () => {
|
||||
const countDown = countDownAndCondition({
|
||||
|
||||
Reference in New Issue
Block a user