Compare commits
2 Commits
api-donasi
...
api/10-oct
| Author | SHA1 | Date | |
|---|---|---|---|
| 0e7b29bb15 | |||
| b293310969 |
@@ -10,7 +10,6 @@ export default function UserLayout() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack screenOptions={HeaderStyles}>
|
<Stack screenOptions={HeaderStyles}>
|
||||||
|
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="waiting-room"
|
name="waiting-room"
|
||||||
options={{
|
options={{
|
||||||
@@ -463,7 +462,7 @@ export default function UserLayout() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="donation/[id]/(transaction-flow)/[transaction]/process"
|
name="donation/[id]/(transaction-flow)/[invoiceId]/process"
|
||||||
options={{
|
options={{
|
||||||
title: "Proses",
|
title: "Proses",
|
||||||
headerLeft: () => (
|
headerLeft: () => (
|
||||||
@@ -477,14 +476,14 @@ export default function UserLayout() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="donation/[id]/(transaction-flow)/[transaction]/success"
|
name="donation/[id]/(transaction-flow)/[invoiceId]/success"
|
||||||
options={{
|
options={{
|
||||||
title: "Donasi Berhasil",
|
title: "Donasi Berhasil",
|
||||||
headerLeft: () => <BackButton />,
|
headerLeft: () => <BackButton />,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="donation/[id]/(transaction-flow)/[transaction]/failed"
|
name="donation/[id]/(transaction-flow)/[invoiceId]/failed"
|
||||||
options={{
|
options={{
|
||||||
title: "Donasi Gagal",
|
title: "Donasi Gagal",
|
||||||
headerLeft: () => <BackButton />,
|
headerLeft: () => <BackButton />,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BadgeCustom,
|
BadgeCustom,
|
||||||
BaseBox,
|
BaseBox,
|
||||||
@@ -9,7 +10,6 @@ import {
|
|||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import { dummyMasterStatusTransaction } from "@/lib/dummy-data/_master/status-transaction";
|
|
||||||
import { apiDonationGetAll } from "@/service/api-client/api-donation";
|
import { apiDonationGetAll } from "@/service/api-client/api-donation";
|
||||||
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
import { Href, router, useFocusEffect } from "expo-router";
|
import { Href, router, useFocusEffect } from "expo-router";
|
||||||
@@ -25,7 +25,7 @@ export default function DonationMyDonation() {
|
|||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
onLoadData();
|
onLoadData();
|
||||||
}, [])
|
}, [user?.id])
|
||||||
);
|
);
|
||||||
|
|
||||||
const onLoadData = async () => {
|
const onLoadData = async () => {
|
||||||
@@ -48,6 +48,18 @@ export default function DonationMyDonation() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 = ({
|
const handlePress = ({
|
||||||
invoiceId,
|
invoiceId,
|
||||||
donationId,
|
donationId,
|
||||||
@@ -57,15 +69,15 @@ export default function DonationMyDonation() {
|
|||||||
donationId: string;
|
donationId: string;
|
||||||
status: string;
|
status: string;
|
||||||
}) => {
|
}) => {
|
||||||
const url: Href = `../${donationId}/(transaction-flow)/${invoiceId}/invoice`;
|
const url: Href = `../${donationId}/(transaction-flow)/${invoiceId}`;
|
||||||
if (status === "menunggu") {
|
if (status === "menunggu") {
|
||||||
router.push(url);
|
router.push(`${url}/invoice`);
|
||||||
} else if (status === "proses") {
|
} else if (status === "proses") {
|
||||||
router.push(url);
|
router.push(`${url}/process`);
|
||||||
} else if (status === "berhasil") {
|
} else if (status === "berhasil") {
|
||||||
router.push(url);
|
router.push(`${url}/success`);
|
||||||
} else if (status === "gagal") {
|
} else if (status === "gagal") {
|
||||||
router.push(url);
|
router.push(`${url}/failed`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -112,7 +124,11 @@ export default function DonationMyDonation() {
|
|||||||
Rp. {formatCurrencyDisplay(item.nominal)}
|
Rp. {formatCurrencyDisplay(item.nominal)}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
|
|
||||||
<BadgeCustom variant="light" color={item.color} fullWidth>
|
<BadgeCustom
|
||||||
|
variant="light"
|
||||||
|
color={handlerColor(_.lowerCase(item.statusInvoice))}
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
{item.statusInvoice}
|
{item.statusInvoice}
|
||||||
</BadgeCustom>
|
</BadgeCustom>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
ButtonCenteredOnly,
|
ButtonCenteredOnly,
|
||||||
ButtonCustom,
|
ButtonCustom,
|
||||||
@@ -9,17 +10,120 @@ import {
|
|||||||
TextInputCustom,
|
TextInputCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { router } from "expo-router";
|
import API_STRORAGE from "@/constants/base-url-api-strorage";
|
||||||
|
import DIRECTORY_ID from "@/constants/directory-id";
|
||||||
|
import {
|
||||||
|
apiDonationGetNewsById,
|
||||||
|
apiDonationUpdateNews,
|
||||||
|
} from "@/service/api-client/api-donation";
|
||||||
|
import { uploadFileService } from "@/service/upload-service";
|
||||||
|
import pickFile, { IFileData } from "@/utils/pickFile";
|
||||||
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function DonationEditNews() {
|
export default function DonationEditNews() {
|
||||||
|
const { news } = useLocalSearchParams();
|
||||||
|
const [data, setData] = useState<any>(null);
|
||||||
|
const [image, setImage] = useState<IFileData | null>(null);
|
||||||
|
const [isLoading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [news])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiDonationGetNewsById({
|
||||||
|
id: news as string,
|
||||||
|
category: "get-one",
|
||||||
|
});
|
||||||
|
|
||||||
|
setData(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlerSubmitUpdate = async () => {
|
||||||
|
let newData;
|
||||||
|
if (!data.title || !data.deskripsi) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Judul dan deskripsi harus diisi",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
newData = {
|
||||||
|
title: data?.title,
|
||||||
|
deskripsi: data?.deskripsi,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (image && image?.uri) {
|
||||||
|
const uploadNewImage = await uploadFileService({
|
||||||
|
dirId: DIRECTORY_ID.donasi_kabar,
|
||||||
|
imageUri: image?.uri,
|
||||||
|
});
|
||||||
|
|
||||||
|
newData = {
|
||||||
|
title: data?.title,
|
||||||
|
deskripsi: data?.deskripsi,
|
||||||
|
newImageId: uploadNewImage.data.id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await apiDonationUpdateNews({
|
||||||
|
id: news as string,
|
||||||
|
data: newData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal mengupdate berita",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Berita berhasil diperbarui",
|
||||||
|
});
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
<StackCustom gap={"xs"}>
|
<StackCustom gap={"xs"}>
|
||||||
<InformationBox text="Upload gambar bersifat opsional untuk melengkapi kabar terkait donasi Anda." />
|
<InformationBox text="Upload gambar bersifat opsional untuk melengkapi kabar terkait donasi Anda." />
|
||||||
<LandscapeFrameUploaded />
|
<LandscapeFrameUploaded
|
||||||
|
image={
|
||||||
|
image
|
||||||
|
? image.uri
|
||||||
|
: data && data.imageId
|
||||||
|
? API_STRORAGE.GET({ fileId: data.imageId })
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
<ButtonCenteredOnly
|
<ButtonCenteredOnly
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push("/(application)/(image)/take-picture/123");
|
pickFile({
|
||||||
|
allowedType: "image",
|
||||||
|
setImageUri(file) {
|
||||||
|
setImage(file);
|
||||||
|
},
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
icon="upload"
|
icon="upload"
|
||||||
>
|
>
|
||||||
@@ -30,6 +134,8 @@ export default function DonationEditNews() {
|
|||||||
label="Judul Berita"
|
label="Judul Berita"
|
||||||
placeholder="Masukan judul berita"
|
placeholder="Masukan judul berita"
|
||||||
required
|
required
|
||||||
|
value={data?.title}
|
||||||
|
onChangeText={(value) => setData({ ...data, title: value })}
|
||||||
/>
|
/>
|
||||||
<TextAreaCustom
|
<TextAreaCustom
|
||||||
label="Deskripsi Berita"
|
label="Deskripsi Berita"
|
||||||
@@ -37,12 +143,16 @@ export default function DonationEditNews() {
|
|||||||
required
|
required
|
||||||
showCount
|
showCount
|
||||||
maxLength={1000}
|
maxLength={1000}
|
||||||
|
value={data?.deskripsi}
|
||||||
|
onChangeText={(value) => setData({ ...data, deskripsi: value })}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Spacing />
|
<Spacing />
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
|
disabled={!data?.title || !data?.deskripsi}
|
||||||
|
isLoading={isLoading}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.back();
|
handlerSubmitUpdate();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Update
|
Update
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
AlertDefaultSystem,
|
AlertDefaultSystem,
|
||||||
BackButton,
|
BackButton,
|
||||||
@@ -12,13 +13,45 @@ import {
|
|||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { IconEdit } from "@/components/_Icon";
|
import { IconEdit } from "@/components/_Icon";
|
||||||
import { IconTrash } from "@/components/_Icon/IconTrash";
|
import { IconTrash } from "@/components/_Icon/IconTrash";
|
||||||
import dayjs from "dayjs";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
import {
|
||||||
import { useState } from "react";
|
apiDonationDeleteNews,
|
||||||
|
apiDonationGetNewsById,
|
||||||
|
} from "@/service/api-client/api-donation";
|
||||||
|
import { formatChatTime } from "@/utils/formatChatTime";
|
||||||
|
import {
|
||||||
|
router,
|
||||||
|
Stack,
|
||||||
|
useFocusEffect,
|
||||||
|
useLocalSearchParams,
|
||||||
|
} from "expo-router";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function DonationNews() {
|
export default function DonationNews() {
|
||||||
const { id, news } = useLocalSearchParams();
|
const { user } = useAuth();
|
||||||
|
const { news } = useLocalSearchParams();
|
||||||
const [openDrawer, setOpenDrawer] = useState(false);
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
const [data, setData] = useState<any>(null);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [news])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiDonationGetNewsById({
|
||||||
|
id: news as string,
|
||||||
|
category: "get-one",
|
||||||
|
});
|
||||||
|
|
||||||
|
setData(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -26,28 +59,28 @@ export default function DonationNews() {
|
|||||||
options={{
|
options={{
|
||||||
title: "Detail Kabar",
|
title: "Detail Kabar",
|
||||||
headerLeft: () => <BackButton />,
|
headerLeft: () => <BackButton />,
|
||||||
headerRight: () => <DotButton onPress={() => setOpenDrawer(true)} />,
|
headerRight: () =>
|
||||||
|
user?.id === data?.authorId && (
|
||||||
|
<DotButton onPress={() => setOpenDrawer(true)} />
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
<BaseBox>
|
<BaseBox>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<TextCustom style={{ alignSelf: "flex-end" }}>
|
<TextCustom style={{ alignSelf: "flex-end" }}>
|
||||||
{dayjs().format("DD MMM YYYY")}
|
{formatChatTime(data?.createdAt)}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
|
|
||||||
<DummyLandscapeImage />
|
{data && data.imageId && (
|
||||||
|
<DummyLandscapeImage imageId={data.imageId} />
|
||||||
|
)}
|
||||||
|
|
||||||
<TextCustom bold size="large" align="center">
|
<TextCustom bold size="large" align="center">
|
||||||
Judul Berita
|
{data?.title || "-"}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
|
|
||||||
<TextCustom>
|
<TextCustom>{data?.deskripsi || "-"}</TextCustom>
|
||||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Sapiente
|
|
||||||
est id temporibus perferendis eos reiciendis reprehenderit tempora
|
|
||||||
ut quibusdam dolores facilis rerum exercitationem recusandae quis
|
|
||||||
neque, adipisci dolorum, aspernatur labore?
|
|
||||||
</TextCustom>
|
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
@@ -62,12 +95,12 @@ export default function DonationNews() {
|
|||||||
{
|
{
|
||||||
icon: <IconEdit />,
|
icon: <IconEdit />,
|
||||||
label: "Edit Berita",
|
label: "Edit Berita",
|
||||||
path: `/donation/${id}/(news)/${news}/edit-news` as any,
|
path: `/donation/[id]/(news)/${news}/edit-news` as any,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: <IconTrash />,
|
icon: <IconTrash />,
|
||||||
label: "Hapus Berita",
|
label: "Hapus Berita",
|
||||||
path: `` as any,
|
path: "",
|
||||||
color: "red",
|
color: "red",
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
@@ -79,7 +112,23 @@ export default function DonationNews() {
|
|||||||
message: "Apakah Anda yakin ingin menghapus berita ini?",
|
message: "Apakah Anda yakin ingin menghapus berita ini?",
|
||||||
textLeft: "Batal",
|
textLeft: "Batal",
|
||||||
textRight: "Hapus",
|
textRight: "Hapus",
|
||||||
onPressRight: () => {
|
onPressRight: async () => {
|
||||||
|
const response = await apiDonationDeleteNews({
|
||||||
|
id: news as string,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal menghapus berita",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Berita berhasil dihapus",
|
||||||
|
});
|
||||||
router.back();
|
router.back();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,17 +9,79 @@ import {
|
|||||||
TextInputCustom,
|
TextInputCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { router } from "expo-router";
|
import DIRECTORY_ID from "@/constants/directory-id";
|
||||||
|
import { apiDonationCreateNews } from "@/service/api-client/api-donation";
|
||||||
|
import { uploadFileService } from "@/service/upload-service";
|
||||||
|
import pickFile, { IFileData } from "@/utils/pickFile";
|
||||||
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useState } from "react";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function DonationAddNews() {
|
export default function DonationAddNews() {
|
||||||
|
const { id } = useLocalSearchParams();
|
||||||
|
const [data, setData] = useState({
|
||||||
|
title: "",
|
||||||
|
deskripsi: "",
|
||||||
|
});
|
||||||
|
const [image, setImage] = useState<IFileData | null>(null);
|
||||||
|
const [isLoading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const handlerSubmit = async () => {
|
||||||
|
let newData: any = { ...data };
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
if (image) {
|
||||||
|
const responseUploadImage = await uploadFileService({
|
||||||
|
dirId: DIRECTORY_ID.donasi_kabar,
|
||||||
|
imageUri: image?.uri,
|
||||||
|
});
|
||||||
|
|
||||||
|
newData = {
|
||||||
|
...newData,
|
||||||
|
imageId: responseUploadImage.data.id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await apiDonationCreateNews({
|
||||||
|
id: id as string,
|
||||||
|
data: newData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal menambah berita",
|
||||||
|
});
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Berita berhasil ditambahkan",
|
||||||
|
});
|
||||||
|
|
||||||
|
router.back();
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
<StackCustom gap={"xs"}>
|
<StackCustom gap={"xs"}>
|
||||||
<InformationBox text="Upload gambar bersifat opsional untuk melengkapi kabar terkait donasi Anda." />
|
<InformationBox text="Upload gambar bersifat opsional untuk melengkapi kabar terkait donasi Anda." />
|
||||||
<LandscapeFrameUploaded />
|
<LandscapeFrameUploaded image={image?.uri} />
|
||||||
<ButtonCenteredOnly
|
<ButtonCenteredOnly
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push("/(application)/(image)/take-picture/123");
|
pickFile({
|
||||||
|
allowedType: "image",
|
||||||
|
setImageUri(file) {
|
||||||
|
setImage(file);
|
||||||
|
},
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
icon="upload"
|
icon="upload"
|
||||||
>
|
>
|
||||||
@@ -30,6 +92,13 @@ export default function DonationAddNews() {
|
|||||||
label="Judul Berita"
|
label="Judul Berita"
|
||||||
placeholder="Masukan judul berita"
|
placeholder="Masukan judul berita"
|
||||||
required
|
required
|
||||||
|
value={data.title}
|
||||||
|
onChangeText={(value) => {
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
title: value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<TextAreaCustom
|
<TextAreaCustom
|
||||||
label="Deskripsi Berita"
|
label="Deskripsi Berita"
|
||||||
@@ -37,12 +106,21 @@ export default function DonationAddNews() {
|
|||||||
required
|
required
|
||||||
showCount
|
showCount
|
||||||
maxLength={1000}
|
maxLength={1000}
|
||||||
|
value={data.deskripsi}
|
||||||
|
onChangeText={(value) => {
|
||||||
|
setData({
|
||||||
|
...data,
|
||||||
|
deskripsi: value,
|
||||||
|
});
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Spacing />
|
<Spacing />
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
|
disabled={!data.title || !data.deskripsi}
|
||||||
|
isLoading={isLoading}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.back();
|
handlerSubmit();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Simpan
|
Simpan
|
||||||
|
|||||||
@@ -1,45 +1,88 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BackButton,
|
BackButton,
|
||||||
BaseBox,
|
BaseBox,
|
||||||
DrawerCustom,
|
DrawerCustom,
|
||||||
Grid,
|
Grid,
|
||||||
MenuDrawerDynamicGrid,
|
LoaderCustom,
|
||||||
TextCustom,
|
MenuDrawerDynamicGrid,
|
||||||
ViewWrapper
|
TextCustom,
|
||||||
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { IconPlus } from "@/components/_Icon";
|
import { IconPlus } from "@/components/_Icon";
|
||||||
import dayjs from "dayjs";
|
import { apiDonationGetNewsById } from "@/service/api-client/api-donation";
|
||||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
import { formatChatTime } from "@/utils/formatChatTime";
|
||||||
import { useState } from "react";
|
import {
|
||||||
|
router,
|
||||||
|
Stack,
|
||||||
|
useFocusEffect,
|
||||||
|
useLocalSearchParams,
|
||||||
|
} from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export default function DonationRecapOfNews() {
|
export default function DonationRecapOfNews() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
const [openDrawer, setOpenDrawer] = useState(false);
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
const [list, setList] = useState<any[] | null>(null);
|
||||||
|
const [loadList, setLoadList] = useState<boolean>(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadList();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadList = async () => {
|
||||||
|
try {
|
||||||
|
setLoadList(true);
|
||||||
|
const response = await apiDonationGetNewsById({
|
||||||
|
id: id as string,
|
||||||
|
category: "get-all",
|
||||||
|
});
|
||||||
|
|
||||||
|
setList(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
setList([]);
|
||||||
|
} finally {
|
||||||
|
setLoadList(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
options={{
|
options={{
|
||||||
title: "Daftar Kabar",
|
title: "Daftar Kabar",
|
||||||
headerLeft: () => <BackButton />, }}
|
headerLeft: () => <BackButton />,
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
{Array.from({ length: 15 }).map((_, index) => (
|
{loadList ? (
|
||||||
<BaseBox key={index} href={`/donation/${id}/(news)/${index}`}>
|
<LoaderCustom />
|
||||||
<Grid>
|
) : _.isEmpty(list) ? (
|
||||||
<Grid.Col span={8}>
|
<TextCustom align="center" color="gray">
|
||||||
<TextCustom truncate bold>
|
Tidak ada kabar
|
||||||
Lorem ipsum dolor, sit amet consectetur adipisicing elit.
|
</TextCustom>
|
||||||
</TextCustom>
|
) : (
|
||||||
</Grid.Col>
|
list?.map((item: any, index: number) => (
|
||||||
<Grid.Col span={4} style={{ alignItems: "flex-end" }}>
|
<BaseBox key={index} href={`/donation/[id]/(news)/${item.id}`}>
|
||||||
<TextCustom size="small">
|
<Grid>
|
||||||
{dayjs().format("DD MMM YYYY")}
|
<Grid.Col span={8}>
|
||||||
</TextCustom>
|
<TextCustom truncate bold>
|
||||||
</Grid.Col>
|
{item?.title || "-"}
|
||||||
</Grid>
|
</TextCustom>
|
||||||
</BaseBox>
|
</Grid.Col>
|
||||||
))}
|
<Grid.Col span={4} style={{ alignItems: "flex-end" }}>
|
||||||
|
<TextCustom size="small">
|
||||||
|
{formatChatTime(item?.createdAt)}
|
||||||
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
))
|
||||||
|
)}
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
|
|
||||||
<DrawerCustom
|
<DrawerCustom
|
||||||
|
|||||||
@@ -1,21 +1,55 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BackButton,
|
BackButton,
|
||||||
BaseBox,
|
BaseBox,
|
||||||
DotButton,
|
DotButton,
|
||||||
DrawerCustom,
|
DrawerCustom,
|
||||||
Grid,
|
Grid,
|
||||||
|
LoaderCustom,
|
||||||
MenuDrawerDynamicGrid,
|
MenuDrawerDynamicGrid,
|
||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
import { IconPlus } from "@/components/_Icon";
|
import { IconPlus } from "@/components/_Icon";
|
||||||
import dayjs from "dayjs";
|
import { apiDonationGetNewsById } from "@/service/api-client/api-donation";
|
||||||
import { router, Stack, useLocalSearchParams } from "expo-router";
|
import { formatChatTime } from "@/utils/formatChatTime";
|
||||||
import { useState } from "react";
|
import {
|
||||||
|
router,
|
||||||
|
Stack,
|
||||||
|
useFocusEffect,
|
||||||
|
useLocalSearchParams,
|
||||||
|
} from "expo-router";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
|
||||||
export default function DonationRecapOfNews() {
|
export default function DonationRecapOfNews() {
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
const [openDrawer, setOpenDrawer] = useState(false);
|
const [openDrawer, setOpenDrawer] = useState(false);
|
||||||
|
const [list, setList] = useState<any[] | null>(null);
|
||||||
|
const [loadList, setLoadList] = useState<boolean>(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadList();
|
||||||
|
}, [id])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadList = async () => {
|
||||||
|
try {
|
||||||
|
setLoadList(true);
|
||||||
|
const response = await apiDonationGetNewsById({
|
||||||
|
id: id as string,
|
||||||
|
category: "get-all",
|
||||||
|
});
|
||||||
|
|
||||||
|
setList(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
setList([]);
|
||||||
|
} finally {
|
||||||
|
setLoadList(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -27,20 +61,30 @@ export default function DonationRecapOfNews() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
{Array.from({ length: 15 }).map((_, index) => (
|
{loadList ? (
|
||||||
<BaseBox key={index} href={`/donation/${id}/(news)/${index}`}>
|
<LoaderCustom />
|
||||||
<Grid>
|
) : _.isEmpty(list) ? (
|
||||||
<Grid.Col span={8}>
|
<TextCustom align="center" color="gray">
|
||||||
<TextCustom truncate bold>
|
Tidak ada kabar
|
||||||
Lorem ipsum dolor, sit amet consectetur adipisicing elit.
|
</TextCustom>
|
||||||
</TextCustom>
|
) : (
|
||||||
</Grid.Col>
|
list?.map((item: any, index: number) => (
|
||||||
<Grid.Col span={4} style={{ alignItems: "flex-end" }}>
|
<BaseBox key={index} href={`/donation/[id]/(news)/${item.id}`}>
|
||||||
<TextCustom size="small">{dayjs().format("DD MMM YYYY")}</TextCustom>
|
<Grid>
|
||||||
</Grid.Col>
|
<Grid.Col span={8}>
|
||||||
</Grid>
|
<TextCustom truncate bold>
|
||||||
</BaseBox>
|
{item?.title || "-"}
|
||||||
))}
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col span={4} style={{ alignItems: "flex-end" }}>
|
||||||
|
<TextCustom size="small">
|
||||||
|
{formatChatTime(item?.createdAt)}
|
||||||
|
</TextCustom>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
|
</BaseBox>
|
||||||
|
))
|
||||||
|
)}
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
|
|
||||||
<DrawerCustom
|
<DrawerCustom
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import {
|
import {
|
||||||
BaseBox,
|
BaseBox,
|
||||||
ButtonCenteredOnly,
|
ButtonCenteredOnly,
|
||||||
@@ -9,23 +10,107 @@ import {
|
|||||||
TextCustom,
|
TextCustom,
|
||||||
ViewWrapper,
|
ViewWrapper,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
|
import CopyButton from "@/components/Button/CoyButton";
|
||||||
import { MainColor } from "@/constants/color-palet";
|
import { MainColor } from "@/constants/color-palet";
|
||||||
import { router, useLocalSearchParams } from "expo-router";
|
import DIRECTORY_ID from "@/constants/directory-id";
|
||||||
|
import {
|
||||||
|
apiDonationGetInvoiceById,
|
||||||
|
apiDonationUpdateInvoice,
|
||||||
|
} from "@/service/api-client/api-donation";
|
||||||
|
import { uploadFileService } from "@/service/upload-service";
|
||||||
|
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
|
||||||
|
import pickFile from "@/utils/pickFile";
|
||||||
|
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
||||||
|
import { useCallback, useState } from "react";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import Toast from "react-native-toast-message";
|
||||||
|
|
||||||
export default function DonationInvoice() {
|
export default function DonationInvoice() {
|
||||||
const { invoiceId } = useLocalSearchParams();
|
const { invoiceId } = useLocalSearchParams();
|
||||||
console.log("invoiceId", invoiceId);
|
console.log("invoiceId", invoiceId);
|
||||||
|
const [data, setData] = useState<any>(null);
|
||||||
|
const [image, setImage] = useState<any>(null);
|
||||||
|
const [isLoading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
useFocusEffect(
|
||||||
|
useCallback(() => {
|
||||||
|
onLoadData();
|
||||||
|
}, [invoiceId])
|
||||||
|
);
|
||||||
|
|
||||||
|
const onLoadData = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiDonationGetInvoiceById({
|
||||||
|
id: invoiceId as string,
|
||||||
|
});
|
||||||
|
console.log("[RESPONSE]", JSON.stringify(response, null, 2));
|
||||||
|
setData(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlerUpdateInvoice = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const responseUploadImage = await uploadFileService({
|
||||||
|
dirId: DIRECTORY_ID.donasi_bukti_transfer,
|
||||||
|
imageUri: image?.uri,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[RESPONSE UPLOAD IMAGE]", responseUploadImage);
|
||||||
|
|
||||||
|
if (!responseUploadImage?.data?.id) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal mengunggah bukti transfer",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileId = responseUploadImage?.data?.id;
|
||||||
|
|
||||||
|
const response = await apiDonationUpdateInvoice({
|
||||||
|
id: invoiceId as string,
|
||||||
|
fileId: fileId,
|
||||||
|
status: "proses",
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[RESPONSE UPDATE]", JSON.stringify(response, null, 2));
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
Toast.show({
|
||||||
|
type: "error",
|
||||||
|
text1: "Gagal mengunggah bukti transfer",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.show({
|
||||||
|
type: "success",
|
||||||
|
text1: "Berhasil mengunggah bukti transfer",
|
||||||
|
});
|
||||||
|
router.replace(`/donation/[id]/(transaction-flow)/${invoiceId}/process`);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("[ERROR]", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ViewWrapper>
|
<ViewWrapper>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<InformationBox
|
<InformationBox
|
||||||
text={`Mohon transfer donasi anda ke rekening dibawah dengan Id: ${invoiceId}`}
|
text={`Mohon transfer donasi anda ke rekening dibawah`}
|
||||||
/>
|
/>
|
||||||
<BaseBox>
|
<BaseBox>
|
||||||
<StackCustom gap={"xs"}>
|
<StackCustom gap={"xs"}>
|
||||||
<TextCustom>Nama BANK</TextCustom>
|
<TextCustom bold>
|
||||||
<TextCustom>Nama Penerima</TextCustom>
|
BANK: {data?.DonasiMaster_Bank?.name}
|
||||||
|
</TextCustom>
|
||||||
|
{/* <TextCustom>{data?.DonasiMaster_Bank?.accountName}</TextCustom> */}
|
||||||
<Spacing height={10} />
|
<Spacing height={10} />
|
||||||
|
|
||||||
<BaseBox backgroundColor={MainColor.soft_darkblue}>
|
<BaseBox backgroundColor={MainColor.soft_darkblue}>
|
||||||
@@ -37,7 +122,7 @@ export default function DonationInvoice() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TextCustom size="xlarge" bold color="yellow">
|
<TextCustom size="xlarge" bold color="yellow">
|
||||||
4567898765433567
|
{data?.DonasiMaster_Bank?.norek}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col
|
<Grid.Col
|
||||||
@@ -46,7 +131,7 @@ export default function DonationInvoice() {
|
|||||||
alignItems: "flex-end",
|
alignItems: "flex-end",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ButtonCustom>Salin</ButtonCustom>
|
<CopyButton textToCopy={data?.DonasiMaster_Bank?.norek} />
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
@@ -68,7 +153,7 @@ export default function DonationInvoice() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TextCustom size="xlarge" bold color="yellow">
|
<TextCustom size="xlarge" bold color="yellow">
|
||||||
Rp. 1.000.000
|
Rp. {formatCurrencyDisplay(data?.nominal) || "-"}
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
<Grid.Col
|
<Grid.Col
|
||||||
@@ -77,7 +162,7 @@ export default function DonationInvoice() {
|
|||||||
alignItems: "flex-end",
|
alignItems: "flex-end",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ButtonCustom>Salin</ButtonCustom>
|
<CopyButton textToCopy={data?.nominal} />
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
@@ -86,10 +171,32 @@ export default function DonationInvoice() {
|
|||||||
|
|
||||||
<BaseBox>
|
<BaseBox>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<TextCustom>Upload bukti transfer anda.</TextCustom>
|
<TextCustom bold align="center" size={"small"} color="gray">
|
||||||
|
Upload bukti transfer anda.
|
||||||
|
</TextCustom>
|
||||||
|
{image ? (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
gap: 10,
|
||||||
|
paddingInline: 20,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextCustom bold align="center" truncate>
|
||||||
|
{image?.name}
|
||||||
|
</TextCustom>
|
||||||
|
</View>
|
||||||
|
) : null}
|
||||||
<ButtonCenteredOnly
|
<ButtonCenteredOnly
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push("/(application)/(image)/take-picture/123");
|
pickFile({
|
||||||
|
allowedType: "image",
|
||||||
|
setImageUri(file) {
|
||||||
|
setImage(file);
|
||||||
|
},
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
icon="upload"
|
icon="upload"
|
||||||
>
|
>
|
||||||
@@ -99,11 +206,13 @@ export default function DonationInvoice() {
|
|||||||
</BaseBox>
|
</BaseBox>
|
||||||
|
|
||||||
<ButtonCustom
|
<ButtonCustom
|
||||||
|
disabled={!image}
|
||||||
|
isLoading={isLoading}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
router.push(`/donation/${invoiceId}/(transaction-flow)/process`);
|
handlerUpdateInvoice();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Saya Sudah Transfer
|
Simpan
|
||||||
</ButtonCustom>
|
</ButtonCustom>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
<Spacing />
|
<Spacing />
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
import {
|
import { BaseBox, StackCustom, TextCustom, ViewWrapper } from "@/components";
|
||||||
BaseBox,
|
import MoneyTransferAnimation from "@/components/_ShareComponent/MoneyTransferAnimation";
|
||||||
Grid,
|
import { View } from "react-native";
|
||||||
StackCustom,
|
|
||||||
TextCustom,
|
|
||||||
ViewWrapper,
|
|
||||||
} from "@/components";
|
|
||||||
import { MainColor } from "@/constants/color-palet";
|
|
||||||
import { Ionicons } from "@expo/vector-icons";
|
|
||||||
import { ActivityIndicator } from "react-native";
|
|
||||||
|
|
||||||
export default function DonationProcess() {
|
export default function DonationProcess() {
|
||||||
return (
|
return (
|
||||||
@@ -16,13 +9,16 @@ export default function DonationProcess() {
|
|||||||
<BaseBox>
|
<BaseBox>
|
||||||
<StackCustom>
|
<StackCustom>
|
||||||
<TextCustom align="center" bold>
|
<TextCustom align="center" bold>
|
||||||
Admin sedang memproses transaksi donasimu
|
Admin sedang memvalidasi data dan bukti transfer anda. Mohon
|
||||||
|
tunggu proses ini selesai.
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
<ActivityIndicator size="large" color={MainColor.yellow} />
|
<View style={{ alignItems: "center", justifyContent: "center" }}>
|
||||||
|
<MoneyTransferAnimation />
|
||||||
|
</View>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
|
|
||||||
<BaseBox>
|
{/* <BaseBox>
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Col span={10} style={{ justifyContent: "center" }}>
|
<Grid.Col span={10} style={{ justifyContent: "center" }}>
|
||||||
<TextCustom size="small">
|
<TextCustom size="small">
|
||||||
@@ -38,7 +34,7 @@ export default function DonationProcess() {
|
|||||||
/>
|
/>
|
||||||
</Grid.Col>
|
</Grid.Col>
|
||||||
</Grid>
|
</Grid>
|
||||||
</BaseBox>
|
</BaseBox> */}
|
||||||
</ViewWrapper>
|
</ViewWrapper>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ export default function InvestmentInputDonation() {
|
|||||||
|
|
||||||
const handlerSubmit = async () => {
|
const handlerSubmit = async () => {
|
||||||
try {
|
try {
|
||||||
console.log("jumlah", nominal);
|
|
||||||
await AsyncStorage.setItem(
|
await AsyncStorage.setItem(
|
||||||
LOCAL_STORAGE_KEY.transactionDonation,
|
LOCAL_STORAGE_KEY.transactionDonation,
|
||||||
JSON.stringify({ nominal: nominal.toString() })
|
JSON.stringify({ nominal: nominal.toString() })
|
||||||
@@ -77,6 +76,7 @@ export default function InvestmentInputDonation() {
|
|||||||
|
|
||||||
<BaseBox>
|
<BaseBox>
|
||||||
<TextInputCustom
|
<TextInputCustom
|
||||||
|
keyboardType="numeric"
|
||||||
label="Nominal lainnya"
|
label="Nominal lainnya"
|
||||||
placeholder="0"
|
placeholder="0"
|
||||||
iconLeft="Rp."
|
iconLeft="Rp."
|
||||||
|
|||||||
@@ -7,19 +7,16 @@ import {
|
|||||||
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";
|
||||||
import { useAuth } from "@/hooks/use-auth";
|
import { useAuth } from "@/hooks/use-auth";
|
||||||
import { dummyMasterBank } from "@/lib/dummy-data/_master/bank";
|
|
||||||
import { apiDonationCreateInvoice } from "@/service/api-client/api-donation";
|
import { apiDonationCreateInvoice } from "@/service/api-client/api-donation";
|
||||||
import { apiMasterBank } from "@/service/api-client/api-master";
|
import { apiMasterBank } from "@/service/api-client/api-master";
|
||||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||||
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
|
import { router, useLocalSearchParams } from "expo-router";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
export default function DonationSelectBank() {
|
export default function DonationSelectBank() {
|
||||||
const { user } = useAuth();
|
const { user } = useAuth();
|
||||||
const { id } = useLocalSearchParams();
|
const { id } = useLocalSearchParams();
|
||||||
|
|
||||||
console.log("id", id);
|
|
||||||
const [select, setSelect] = useState<any | number>("");
|
const [select, setSelect] = useState<any | number>("");
|
||||||
const [listBank, setListBank] = useState<any>([]);
|
const [listBank, setListBank] = useState<any>([]);
|
||||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
@@ -54,22 +51,16 @@ export default function DonationSelectBank() {
|
|||||||
authorId: user?.id,
|
authorId: user?.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("[NEW DATA]", newData);
|
|
||||||
|
|
||||||
const response = await apiDonationCreateInvoice({
|
const response = await apiDonationCreateInvoice({
|
||||||
id: id as string,
|
id: id as string,
|
||||||
data: newData,
|
data: newData,
|
||||||
});
|
});
|
||||||
console.log("[RESPONSE CREATE>>]", response);
|
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
const invoiceId = response.data.id;
|
const invoiceId = response.data.id;
|
||||||
|
|
||||||
const delStorage = await AsyncStorage.removeItem(
|
await AsyncStorage.removeItem(LOCAL_STORAGE_KEY.transactionDonation);
|
||||||
LOCAL_STORAGE_KEY.transactionDonation
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log("[DEL STORAGE]", delStorage);
|
|
||||||
router.replace(
|
router.replace(
|
||||||
`/(application)/(user)/donation/[id]/(transaction-flow)/${invoiceId}/invoice`
|
`/(application)/(user)/donation/[id]/(transaction-flow)/${invoiceId}/invoice`
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -32,10 +32,6 @@ export default function DonationInformationFunrising() {
|
|||||||
try {
|
try {
|
||||||
setLoadList(true);
|
setLoadList(true);
|
||||||
const response = await apiDonationFundrising({ id: id as string });
|
const response = await apiDonationFundrising({ id: id as string });
|
||||||
console.log(
|
|
||||||
"[RES GET FUNDRISING]",
|
|
||||||
JSON.stringify(response.data, null, 2)
|
|
||||||
);
|
|
||||||
|
|
||||||
setData(response?.data?.user);
|
setData(response?.data?.user);
|
||||||
setList(response?.data?.donasi);
|
setList(response?.data?.donasi);
|
||||||
@@ -78,7 +74,7 @@ export default function DonationInformationFunrising() {
|
|||||||
{loadList ? (
|
{loadList ? (
|
||||||
<LoaderCustom />
|
<LoaderCustom />
|
||||||
) : _.isEmpty(list) ? (
|
) : _.isEmpty(list) ? (
|
||||||
<TextCustom>Belum ada data</TextCustom>
|
<TextCustom align="center" color="gray" size="small">Belum ada data</TextCustom>
|
||||||
) : (
|
) : (
|
||||||
list?.map((item: any, index: number) => (
|
list?.map((item: any, index: number) => (
|
||||||
<Donation_BoxPublish key={index} id={item?.id} data={item} />
|
<Donation_BoxPublish key={index} id={item?.id} data={item} />
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
import {
|
import { BaseBox, StackCustom, TextCustom, ViewWrapper } from "@/components";
|
||||||
BaseBox,
|
import MoneyTransferAnimation from "@/components/_ShareComponent/MoneyTransferAnimation";
|
||||||
StackCustom,
|
import { View } from "react-native";
|
||||||
TextCustom,
|
|
||||||
ViewWrapper
|
|
||||||
} from "@/components";
|
|
||||||
import { MainColor } from "@/constants/color-palet";
|
|
||||||
import { ActivityIndicator } from "react-native";
|
|
||||||
|
|
||||||
export default function InvestmentProcess() {
|
export default function InvestmentProcess() {
|
||||||
return (
|
return (
|
||||||
@@ -17,7 +12,9 @@ export default function InvestmentProcess() {
|
|||||||
Admin sedang memvalidasi data dan bukti transfer anda. Mohon
|
Admin sedang memvalidasi data dan bukti transfer anda. Mohon
|
||||||
tunggu proses ini selesai.
|
tunggu proses ini selesai.
|
||||||
</TextCustom>
|
</TextCustom>
|
||||||
<ActivityIndicator size="large" color={MainColor.yellow} />
|
<View style={{ alignItems: "center", justifyContent: "center" }}>
|
||||||
|
<MoneyTransferAnimation />
|
||||||
|
</View>
|
||||||
</StackCustom>
|
</StackCustom>
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
|
|
||||||
|
|||||||
118
components/_ShareComponent/MoneyTransferAnimation.tsx
Normal file
118
components/_ShareComponent/MoneyTransferAnimation.tsx
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
|
// MoneyTransferAnimation.tsx
|
||||||
|
import React from "react";
|
||||||
|
import { View, StyleSheet } from "react-native";
|
||||||
|
import { FontAwesome } from "@expo/vector-icons";
|
||||||
|
import Animated, {
|
||||||
|
useSharedValue,
|
||||||
|
useAnimatedStyle,
|
||||||
|
withTiming,
|
||||||
|
Easing,
|
||||||
|
runOnJS,
|
||||||
|
} from "react-native-reanimated";
|
||||||
|
import { AccentColor, MainColor } from "@/constants/color-palet";
|
||||||
|
import TextCustom from "../Text/TextCustom";
|
||||||
|
|
||||||
|
const SCREEN_WIDTH = 300; // Lebar area animasi
|
||||||
|
const DURATION = 2500; // Durasi sekali jalan (kiri → kanan)
|
||||||
|
|
||||||
|
const MoneyTransferAnimation: React.FC = () => {
|
||||||
|
const progress = useSharedValue(0);
|
||||||
|
const opacity = useSharedValue(0);
|
||||||
|
|
||||||
|
// Fungsi untuk mereset dan mulai ulang animasi
|
||||||
|
const startAnimation = () => {
|
||||||
|
progress.value = 0;
|
||||||
|
opacity.value = 0;
|
||||||
|
|
||||||
|
// Fade in di awal
|
||||||
|
opacity.value = withTiming(1, { duration: 300 });
|
||||||
|
|
||||||
|
// Gerak kiri → kanan
|
||||||
|
progress.value = withTiming(
|
||||||
|
1,
|
||||||
|
{
|
||||||
|
duration: DURATION,
|
||||||
|
easing: Easing.linear,
|
||||||
|
},
|
||||||
|
(finished) => {
|
||||||
|
if (finished) {
|
||||||
|
// Fade out di akhir
|
||||||
|
opacity.value = withTiming(0, { duration: 300 }, () => {
|
||||||
|
// Setelah fade out, ulangi
|
||||||
|
runOnJS(startAnimation)();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
startAnimation();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const animatedStyle = useAnimatedStyle(() => {
|
||||||
|
return {
|
||||||
|
transform: [
|
||||||
|
{
|
||||||
|
translateX: progress.value * SCREEN_WIDTH,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
opacity: opacity.value,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
{/* Area animasi (track tidak wajib, tapi bisa ditambahkan) */}
|
||||||
|
<View style={styles.track} />
|
||||||
|
|
||||||
|
{/* Ikon uang animasi */}
|
||||||
|
<Animated.View style={[styles.iconContainer, animatedStyle]}>
|
||||||
|
<FontAwesome name="money" size={28} color="#2ecc71" />
|
||||||
|
</Animated.View>
|
||||||
|
|
||||||
|
{/* Teks status */}
|
||||||
|
<View style={styles.textContainer}>
|
||||||
|
<TextCustom bold>Transaksi Sedang Diproses</TextCustom>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
paddingVertical: 30,
|
||||||
|
position: "relative",
|
||||||
|
width: SCREEN_WIDTH,
|
||||||
|
},
|
||||||
|
track: {
|
||||||
|
position: "absolute",
|
||||||
|
top: 20,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
height: 2,
|
||||||
|
backgroundColor: AccentColor.darkblue,
|
||||||
|
borderRadius: 1,
|
||||||
|
},
|
||||||
|
iconContainer: {
|
||||||
|
position: "absolute",
|
||||||
|
top: 4,
|
||||||
|
left: -30, // Mulai di luar kiri
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
textContainer: {
|
||||||
|
marginTop: 40,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "600",
|
||||||
|
color: MainColor.white,
|
||||||
|
textAlign: "center",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default MoneyTransferAnimation;
|
||||||
@@ -110,7 +110,7 @@ export async function apiDonationGetAll({
|
|||||||
category: "beranda" | "my-donation";
|
category: "beranda" | "my-donation";
|
||||||
authorId?: string;
|
authorId?: string;
|
||||||
}) {
|
}) {
|
||||||
const authorQuery = authorId ? `&authorId=${authorId}` : "";
|
const authorQuery = authorId ? `&authorId=${authorId}` : "";
|
||||||
try {
|
try {
|
||||||
const response = await apiConfig.get(
|
const response = await apiConfig.get(
|
||||||
`/mobile/donation?category=${category}${authorQuery}`
|
`/mobile/donation?category=${category}${authorQuery}`
|
||||||
@@ -163,3 +163,95 @@ export async function apiDonationCreateInvoice({
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function apiDonationGetInvoiceById({ id }: { id: string }) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.get(`/mobile/donation/${id}/invoice`);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiDonationUpdateInvoice({
|
||||||
|
id,
|
||||||
|
fileId,
|
||||||
|
status,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
fileId?: string;
|
||||||
|
status: "berhasil" | "gagal" | "proses" | "menunggu";
|
||||||
|
}) {
|
||||||
|
const statusQuery = `?status=${status}`;
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.put(
|
||||||
|
`/mobile/donation/${id}/invoice${statusQuery}`,
|
||||||
|
{
|
||||||
|
data: fileId,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiDonationCreateNews({
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
data: any;
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.post(`/mobile/donation/${id}/news`, {
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiDonationGetNewsById({
|
||||||
|
id,
|
||||||
|
category,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
category: "get-all" | "get-one";
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.get(
|
||||||
|
`/mobile/donation/${id}/news?category=${category}`
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiDonationUpdateNews({
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
}: {
|
||||||
|
id: string;
|
||||||
|
data: any;
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.put(`/mobile/donation/${id}/news`, {
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiDonationDeleteNews({ id }: { id: string }) {
|
||||||
|
try {
|
||||||
|
const response = await apiConfig.delete(`/mobile/donation/${id}/news`);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user