Integrasi API: Donation Admin

Add:
-  screens/Admin/Donation/funDonationUpdateStatus.ts
-  utils/countDownAndCondition.ts

Fix:
- app/(application)/(user)/donation/[id]/index.tsx
- app/(application)/admin/donation/[id]/[status]/index.tsx
- app/(application)/admin/donation/[id]/list-of-donatur.tsx
- app/(application)/admin/donation/[id]/reject-input.tsx
- app/(application)/admin/donation/index.tsx
- app/(application)/admin/event/[id]/[status]/index.tsx
- app/(application)/admin/voting/[id]/[status]/index.tsx
- screens/Admin/Donation/BoxOfDonationStory.tsx
- screens/Donation/BoxPublish.tsx
- screens/Donation/ComponentBoxDetailData.tsx
- service/api-admin/api-admin-donation.ts
- service/api-client/api-master.ts
- utils/colorBadge.ts
git add . && git commit -m
This commit is contained in:
2025-10-28 10:19:47 +08:00
parent 125bf16605
commit 5d4328a139
15 changed files with 487 additions and 132 deletions

View File

@@ -16,20 +16,19 @@ import Donation_ComponentInfoFundrising from "@/screens/Donation/ComponentInfoFu
import Donation_ComponentStoryFunrising from "@/screens/Donation/ComponentStoryFunrising";
import Donation_ProgressSection from "@/screens/Donation/ProgressSection";
import { apiDonationGetOne } from "@/service/api-client/api-donation";
import { countDownAndCondition } from "@/utils/countDownAndCondition";
import {
router,
Stack,
useFocusEffect,
useLocalSearchParams,
} from "expo-router";
import { useCallback, useState } from "react";
import { useCallback, useEffect, useState } from "react";
export default function DonasiDetailBeranda() {
const { user } = useAuth();
const { id } = useLocalSearchParams();
console.log("ID ", id);
const [openDrawer, setOpenDrawer] = useState(false);
const [data, setData] = useState<any>();
useFocusEffect(
@@ -45,21 +44,41 @@ export default function DonasiDetailBeranda() {
category: "permanent",
});
console.log("[RES GET ONE]", JSON.stringify(response.data, null, 2));
setData(response.data);
} catch (error) {
console.log("[ERROR]", error);
}
};
const [value, setValue] = useState({
sisa: 0,
reminder: false,
});
useEffect(() => {
updateCountDown();
}, [data]);
const updateCountDown = () => {
const countDown = countDownAndCondition({
duration: data?.DonasiMaster_Durasi?.name,
publishTime: data?.publishTime,
});
setValue({
sisa: countDown.durationDay,
reminder: countDown.reminder,
});
};
const buttonSection = (
<>
<BoxButtonOnFooter>
<ButtonCustom
disabled={value?.reminder}
onPress={() => router.navigate(`/donation/${id}/(transaction-flow)`)}
>
Donasi
{value?.reminder ? "Waktu berakhir" : "Donasi"}
</ButtonCustom>
</BoxButtonOnFooter>
</>
@@ -80,6 +99,8 @@ export default function DonasiDetailBeranda() {
<ViewWrapper footerComponent={buttonSection}>
<StackCustom>
<Donation_ComponentBoxDetailData
sisaHari={value.sisa}
reminder={value.reminder}
data={data}
bottomSection={<Donation_ProgressSection id={id as string} />}
/>

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
ActionIcon,
AlertDefaultSystem,
@@ -18,97 +19,147 @@ import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButt
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
import AdminButtonReview from "@/components/_ShareComponent/Admin/ButtonReview";
import { GridDetail_4_8 } from "@/components/_ShareComponent/GridDetail_4_8";
import { MainColor } from "@/constants/color-palet";
import ReportBox from "@/components/Box/ReportBox";
import { ICON_SIZE_BUTTON, TEXT_SIZE_LARGE } from "@/constants/constans-value";
import AdminDonation_BoxOfDonationStory from "@/screens/Admin/Donation/BoxOfDonationStory";
import { funUpdateStatusDonation } from "@/screens/Admin/Donation/funDonationUpdateStatus";
import { apiAdminDonationDetailById } from "@/service/api-admin/api-admin-donation";
import { colorBadgeStatus } from "@/utils/colorBadge";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import { Ionicons } from "@expo/vector-icons";
import { router, useLocalSearchParams } from "expo-router";
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash";
import React from "react";
import { View } from "react-native";
import Toast from "react-native-toast-message";
export default function AdminDonationDetail() {
const { id, status } = useLocalSearchParams();
const [openDrawer, setOpenDrawer] = React.useState(false);
const colorBadge = () => {
if (status === "publish") {
return MainColor.green;
} else if (status === "review") {
return MainColor.orange;
} else if (status === "reject") {
return MainColor.red;
} else {
return MainColor.placeholder;
const [data, setData] = React.useState<any | null>(null);
const [isLoading, setIsLoading] = React.useState(false);
useFocusEffect(
React.useCallback(() => {
onLoadData();
}, [id])
);
const onLoadData = async () => {
try {
const response = await apiAdminDonationDetailById({
id: id as string,
});
console.log("[RES GET BY ID]", JSON.stringify(response, null, 2));
if (response.success) {
setData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
setData(null);
}
};
const listData = [
{
label: "Penggalang Dana",
value: `Bagas Banuna ${id}`,
value: (data && data?.Author?.username) || "-",
},
{
label: "Judul",
value: `Donasi Lorem ipsum dolor sit amet, consectetur adipisicing elit.`,
value: (data && data?.title) || "-",
},
{
label: "Status",
value: (
<BadgeCustom color={colorBadge()}>
{_.startCase(status as string)}
</BadgeCustom>
),
value:
data && data?.DonasiMaster_Status?.name ? (
<BadgeCustom
color={colorBadgeStatus({ status: data?.DonasiMaster_Status?.name })}
>
{_.startCase(data?.DonasiMaster_Status?.name)}
</BadgeCustom>
) : (
"-"
),
},
{
label: "Durasi",
value: "30 Hari",
value: (data && data?.DonasiMaster_Durasi?.name) + " hari" || "-",
},
{
label: "Target Dana",
value: "Rp 10.000.000",
value:
data && data?.target
? `Rp. ${formatCurrencyDisplay(data?.target)}`
: "-",
},
{
label: "Kategori",
value: "Kategori Donasi",
value: (data && data?.DonasiMaster_Ketegori?.name) || "-",
},
// {
// label: "Total Donatur",
// value: "-",
// },
// {
// label: "Progress",
// value: "0 %",
// },
// {
// label: "Dana Terkumpul",
// value: "Rp 0",
// },
];
const listPencarianDana = [
{
label: "Total Dana Dicairkan",
value: "Rp 0",
value: `Rp ${(data && data?.totalPencairan) || 0}`,
},
{
label: "Sisa Dana",
value: "Rp 0",
value: `Rp ${(data && data?.terkumpul - data?.totalPencairan) || 0}`,
},
{
label: "Akumulasi Pencairan",
value: "0 kali",
value: `${(data && data?.totalPencairan) || 0} kali`,
},
{
label: "Bank Tujuan",
value: "BNI",
value: (data && data?.namaBank) || "-",
},
{
label: "Nomor Rekening",
value: "123456789",
value: (data && data?.rekening) || "-",
},
];
const handleReport = async ({
changeStatus,
}: {
changeStatus: "publish" | "review" | "reject";
}) => {
try {
setIsLoading(true);
const response = await funUpdateStatusDonation({
id: id as string,
changeStatus,
data: data,
});
if (!response.success) {
Toast.show({
type: "error",
text1: "Update status gagal",
});
return;
}
Toast.show({
type: "success",
text1: "Update status berhasil",
});
router.back();
} catch (error) {
console.log("[ERROR]", error);
} finally {
setIsLoading(false);
}
};
const rightComponent = (
<ActionIcon
icon={<IconDot size={ICON_SIZE_BUTTON} />}
@@ -118,8 +169,6 @@ export default function AdminDonationDetail() {
/>
);
return (
<>
<ViewWrapper
@@ -147,6 +196,7 @@ export default function AdminDonationDetail() {
/>
))}
</StackCustom>
<ButtonCustom
iconLeft={
<Ionicons name="cash-outline" size={ICON_SIZE_BUTTON} />
@@ -179,7 +229,7 @@ export default function AdminDonationDetail() {
<BaseBox>
<StackCustom>
<DummyLandscapeImage />
<DummyLandscapeImage imageId={data?.imageId || ""} />
{listData.map((item, i) => (
<GridDetail_4_8
key={i}
@@ -190,27 +240,33 @@ export default function AdminDonationDetail() {
</StackCustom>
</BaseBox>
<AdminDonation_BoxOfDonationStory data={data?.CeritaDonasi as any} />
{data &&
data?.catatan &&
(status === "review" || status === "reject") && (
<ReportBox text={data?.catatan} />
)}
{status === "review" && (
<StackCustom>
<AdminDonation_BoxOfDonationStory />
<AdminButtonReview
isLoading={isLoading}
onPublish={() => {
AlertDefaultSystem({
title: "Publish",
message: "Apakah anda yakin ingin mempublikasikan data ini?",
textLeft: "Batal",
textRight: "Ya",
onPressLeft: () => {
router.back();
},
onPressRight: () => {
router.back();
handleReport({ changeStatus: "publish" });
},
});
}}
onReject={() => {
router.push(`/admin/donation/${id}/reject-input`);
router.push(
`/admin/donation/${id}/reject-input?status=${status}`
);
}}
/>
</StackCustom>
@@ -218,12 +274,12 @@ export default function AdminDonationDetail() {
{status === "reject" && (
<StackCustom>
<AdminDonation_BoxOfDonationStory />
<AdminButtonReject
title="Tambah Catatan"
onReject={() => {
router.push(`/admin/donation/${id}/reject-input`);
router.push(
`/admin/donation/${id}/reject-input?status=${status}`
);
}}
/>
</StackCustom>

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
ActionIcon,
BadgeCustom,
@@ -10,22 +11,86 @@ import {
import { IconView } from "@/components/_Icon/IconComponent";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import { GridViewCustomSpan } from "@/components/_ShareComponent/GridViewCustomSpan";
import { MainColor } from "@/constants/color-palet";
import { ICON_SIZE_BUTTON } from "@/constants/constans-value";
import { dummyMasterStatusTransaction } from "@/lib/dummy-data/_master/status-transaction";
import { router, useLocalSearchParams } from "expo-router";
import React from "react";
import { apiAdminDonationListOfDonatur } from "@/service/api-admin/api-admin-donation";
import { apiMasterTransaction } from "@/service/api-client/api-master";
import { colorBadgeTransaction } from "@/utils/colorBadge";
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash";
import React, { useEffect } from "react";
import { View } from "react-native";
import { Divider } from "react-native-paper";
export default function AdminDonasiListOfDonatur() {
const { id } = useLocalSearchParams();
console.log("[ID >>]", id);
const [listData, setListData] = React.useState<any[] | null>(null);
const [master, setMaster] = React.useState<any[]>([]);
const [selectStatus, setSelectStatus] = React.useState<
"berhasil" | "gagal" | "proses" | "menunggu" | ""
>("");
useFocusEffect(
React.useCallback(() => {
onLoadData();
}, [id, selectStatus])
);
const onLoadData = async () => {
try {
const response = await apiAdminDonationListOfDonatur({
id: id as string,
status: "" as any,
});
console.log(
"[LIST OF DONATUR]",
JSON.stringify(response, null, 2)
);
if (response.success) {
setListData(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
setListData([]);
}
};
useEffect(() => {
onLoadMaster();
}, []);
const onLoadMaster = async () => {
try {
const response = await apiMasterTransaction();
if (response.success) {
setMaster(response.data);
}
} catch (error) {
console.log("[ERROR]", error);
setMaster([]);
}
};
const searchComponent = (
<View style={{ flexDirection: "row", gap: 5 }}>
<SelectCustom
placeholder="Pilih status transaksi"
data={dummyMasterStatusTransaction}
onChange={(value) => console.log(value)}
data={
_.isEmpty(master)
? []
: master?.map((item: any) => ({
label: item.name,
value: item.name
}))
}
onChange={(value: any) => {
console.log("[SELECT STATUS]", value);
const statusChooses = _.lowerCase(value);
setSelectStatus(statusChooses as any);
}}
styleContainer={{ width: "100%", marginBottom: 0 }}
/>
</View>
@@ -59,7 +124,7 @@ export default function AdminDonasiListOfDonatur() {
/>
<Divider />
<StackCustom>
{Array.from({ length: 10 }).map((_, index) => (
{listData?.map((item: any, index: number) => (
<View key={index}>
<GridViewCustomSpan
span1={3}
@@ -79,15 +144,15 @@ export default function AdminDonasiListOfDonatur() {
}
component2={
<TextCustom bold align="center" truncate>
Bagas Banuna
{item?.Author?.username || "-"}
</TextCustom>
}
component3={
<BadgeCustom
style={{ alignSelf: "center" }}
color={MainColor.green}
color={colorBadgeTransaction({status: item?.DonasiMaster_StatusInvoice?.name})}
>
Berhasil
{item?.DonasiMaster_StatusInvoice?.name}
</BadgeCustom>
}
/>

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
AlertDefaultSystem,
BoxButtonOnFooter,
@@ -6,15 +7,84 @@ import {
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
import { router, useLocalSearchParams } from "expo-router";
import { useState } from "react";
import { funUpdateStatusDonation } from "@/screens/Admin/Donation/funDonationUpdateStatus";
import {
apiAdminDonationDetailById
} from "@/service/api-admin/api-admin-donation";
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import React from "react";
import Toast from "react-native-toast-message";
export default function AdminDonationRejectInput() {
const { id } = useLocalSearchParams();
const [value, setValue] = useState(id as string);
const { id, status } = useLocalSearchParams();
const [data, setData] = React.useState<any | null>(null);
const [isLoading, setIsLoading] = React.useState(false);
useFocusEffect(
React.useCallback(() => {
onLoadData();
}, [id])
);
const onLoadData = async () => {
try {
const response = await apiAdminDonationDetailById({
id: id as string,
});
if (response.success) {
setData(response.data.catatan);
}
} catch (error) {
console.log("[ERROR]", error);
setData(null);
}
};
const handleReport = async ({
changeStatus,
}: {
changeStatus: "publish" | "review" | "reject";
}) => {
try {
setIsLoading(true);
const response = await funUpdateStatusDonation({
id: id as string,
changeStatus,
data: data,
});
if (!response.success) {
Toast.show({
type: "error",
text1: "Report gagal",
});
return
}
Toast.show({
type: "success",
text1: "Report berhasil",
});
if (status === "review") {
router.replace(`/admin/donation/reject/status`);
} else if (status === "reject") {
router.back();
}
} catch (error) {
console.log("[ERROR]", error);
} finally {
setIsLoading(false);
}
};
const buttonSubmit = (
<BoxButtonOnFooter>
<AdminButtonReject
isLoading={isLoading}
title="Reject"
onReject={() =>
AlertDefaultSystem({
@@ -22,12 +92,9 @@ export default function AdminDonationRejectInput() {
message: "Apakah anda yakin ingin menolak data ini?",
textLeft: "Batal",
textRight: "Ya",
onPressLeft: () => {
router.back();
},
onPressRight: () => {
console.log("value:", value);
router.replace(`/admin/donation/reject/status`);
handleReport({ changeStatus: "reject" });
},
})
}
@@ -42,8 +109,8 @@ export default function AdminDonationRejectInput() {
headerComponent={<AdminBackButtonAntTitle title="Penolakan Donasi" />}
>
<TextAreaCustom
value={value}
onChangeText={setValue}
value={data}
onChangeText={setData}
placeholder="Masukan alasan"
required
showCount

View File

@@ -14,7 +14,6 @@ import { useState, useCallback } from "react";
export default function AdminDonation() {
const [data, setData] = useState<any | null>(null);
const [loadData, setLoadData] = useState<boolean>(false);
useFocusEffect(
useCallback(() => {
@@ -24,7 +23,7 @@ export default function AdminDonation() {
const onLoadData = async () => {
try {
setLoadData(true);
const response = await apiAdminDonation({
category: "dashboard",
});
@@ -37,9 +36,7 @@ export default function AdminDonation() {
} catch (error) {
console.log("[ERROR]", error);
setData([]);
} finally {
setLoadData(false);
}
}
};
const listData = [

View File

@@ -1,16 +1,16 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
ActionIcon,
AlertDefaultSystem,
BadgeCustom,
BaseBox,
DrawerCustom,
LoaderCustom,
MenuDrawerDynamicGrid,
Spacing,
StackCustom,
TextCustom,
ViewWrapper,
ActionIcon,
AlertDefaultSystem,
BadgeCustom,
BaseBox,
DrawerCustom,
LoaderCustom,
MenuDrawerDynamicGrid,
Spacing,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import { IconDot, IconList } from "@/components/_Icon/IconComponent";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
@@ -23,7 +23,7 @@ import { useAuth } from "@/hooks/use-auth";
import { funUpdateStatusEvent } from "@/screens/Admin/Event/funUpdateStatus";
import { apiAdminEventById } from "@/service/api-admin/api-admin-event";
import { DEEP_LINK_URL } from "@/service/api-config";
import { colorBadge } from "@/utils/colorBadge";
import { colorBadgeStatus } from "@/utils/colorBadge";
import { dateTimeView } from "@/utils/dateTimeView";
import { router, useFocusEffect, useLocalSearchParams } from "expo-router";
import _ from "lodash";
@@ -74,7 +74,7 @@ export default function AdminEventDetail() {
label: "Status",
value:
(data && (
<BadgeCustom color={colorBadge({ status: status as string })}>
<BadgeCustom color={colorBadgeStatus({ status: status as string })}>
{_.startCase(status as string)}
</BadgeCustom>
)) ||

View File

@@ -1,14 +1,14 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
AlertDefaultSystem,
BadgeCustom,
BaseBox,
CircleContainer,
Grid,
Spacing,
StackCustom,
TextCustom,
ViewWrapper,
AlertDefaultSystem,
BadgeCustom,
BaseBox,
CircleContainer,
Grid,
Spacing,
StackCustom,
TextCustom,
ViewWrapper,
} from "@/components";
import AdminBackButtonAntTitle from "@/components/_ShareComponent/Admin/BackButtonAntTitle";
import AdminButtonReject from "@/components/_ShareComponent/Admin/ButtonReject";
@@ -18,7 +18,7 @@ import ReportBox from "@/components/Box/ReportBox";
import { MainColor } from "@/constants/color-palet";
import funUpdateStatusVoting from "@/screens/Admin/Voting/funUpdateStatus";
import { apiAdminVotingById } from "@/service/api-admin/api-admin-voting";
import { colorBadge } from "@/utils/colorBadge";
import { colorBadgeStatus } from "@/utils/colorBadge";
import { dateTimeView } from "@/utils/dateTimeView";
import { Entypo } from "@expo/vector-icons";
import dayjs from "dayjs";
@@ -68,7 +68,7 @@ export default function AdminVotingDetail() {
label: "Status",
value:
data && data?.Voting_Status?.name ? (
<BadgeCustom color={colorBadge({ status: status as string })}>
<BadgeCustom color={colorBadgeStatus({ status: status as string })}>
{status === "history" ? "Riwayat" : _.startCase(status as string)}
</BadgeCustom>
) : (

View File

@@ -6,7 +6,11 @@ import {
DummyLandscapeImage,
} from "@/components";
export default function AdminDonation_BoxOfDonationStory() {
export default function AdminDonation_BoxOfDonationStory({
data,
}: {
data: any;
}) {
return (
<>
<BaseBox>
@@ -14,19 +18,9 @@ export default function AdminDonation_BoxOfDonationStory() {
<Spacing />
<StackCustom>
<TextCustom>
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Rem magni
perspiciatis eius ipsam provident, impedit, fugiat aliquid nobis
pariatur asperiores fuga quidem temporibus labore, molestias
perferendis optio ipsum. Praesentium, tempore?
</TextCustom>
<DummyLandscapeImage />
<TextCustom>
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Rem magni
perspiciatis eius ipsam provident, impedit, fugiat aliquid nobis
pariatur asperiores fuga quidem temporibus labore, molestias
perferendis optio ipsum. Praesentium, tempore?
</TextCustom>
<TextCustom>{(data && data?.pembukaan) || "-"}</TextCustom>
<DummyLandscapeImage imageId={data?.imageId || "-"} />
<TextCustom>{(data && data?.cerita) || "-"}</TextCustom>
</StackCustom>
</BaseBox>
</>

View File

@@ -0,0 +1,23 @@
import { apiAdminDonationUpdateStatus } from "@/service/api-admin/api-admin-donation";
export const funUpdateStatusDonation = async ({
id,
changeStatus,
data,
}: {
id: string;
changeStatus: "publish" | "review" | "reject";
data?: string;
}) => {
try {
const response = await apiAdminDonationUpdateStatus({
id: id,
changeStatus: changeStatus as any,
data: data,
});
return response;
} catch (error) {
console.log("[ERROR]", error);
throw error;
}
};

View File

@@ -1,11 +1,14 @@
/* eslint-disable react-hooks/exhaustive-deps */
import {
BaseBox,
Grid,
DummyLandscapeImage,
Grid,
ProgressCustom,
StackCustom,
TextCustom,
ProgressCustom,
} from "@/components";
import { countDownAndCondition } from "@/utils/countDownAndCondition";
import { useEffect, useState } from "react";
import { View } from "react-native";
export default function Donation_BoxPublish({
@@ -15,6 +18,27 @@ export default function Donation_BoxPublish({
id: string;
data: any;
}) {
const [value, setValue] = useState({
sisa: 0,
reminder: false,
});
useEffect(() => {
updateCountDown();
}, [data]);
const updateCountDown = () => {
const countDown = countDownAndCondition({
duration: data?.durasiDonasi,
publishTime: data?.publishTime,
});
setValue({
sisa: countDown.durationDay,
reminder: countDown.reminder,
});
};
return (
<>
<BaseBox paddingTop={7} paddingBottom={7} href={`/donation/${id}`}>
@@ -36,7 +60,13 @@ export default function Donation_BoxPublish({
{data?.title || "-"}
</TextCustom>
<TextCustom size="small">
Sisa hari: {data?.durasiDonasi || 0}
{value.reminder ? (
<TextCustom bold color="red">
Waktu berakhir
</TextCustom>
) : (
<TextCustom>Sisa hari: {value.sisa}</TextCustom>
)}
</TextCustom>
</View>
<ProgressCustom

View File

@@ -1,9 +1,9 @@
import {
BaseBox,
StackCustom,
DummyLandscapeImage,
TextCustom,
Grid,
StackCustom,
TextCustom,
} from "@/components";
import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay";
import React from "react";
@@ -12,10 +12,15 @@ import { View } from "react-native";
export default function Donation_ComponentBoxDetailData({
bottomSection,
data,
sisaHari,
reminder,
}: {
bottomSection?: React.ReactNode;
data: any;
sisaHari: number;
reminder: boolean;
}) {
return (
<>
<BaseBox>
@@ -25,9 +30,13 @@ export default function Donation_ComponentBoxDetailData({
<TextCustom bold size="large">
{data?.title || "-"}
</TextCustom>
<TextCustom size="small">
Durasi: {data?.DonasiMaster_Durasi?.name || "-"}
</TextCustom>
{reminder ? (
<TextCustom bold color="red">
Waktu berakhir
</TextCustom>
) : (
<TextCustom>Sisa hari: {sisaHari}</TextCustom>
)}
</View>
<Grid>

View File

@@ -4,7 +4,7 @@ export async function apiAdminDonation({
category,
search,
}: {
category: "dashboard" | "publish" | "review" | "reject" ;
category: "dashboard" | "publish" | "review" | "reject";
search?: string;
}) {
try {
@@ -16,3 +16,51 @@ export async function apiAdminDonation({
throw error;
}
}
export async function apiAdminDonationDetailById({ id }: { id: string }) {
try {
const response = await apiConfig.get(`/mobile/admin/donation/${id}`);
return response.data;
} catch (error) {
throw error;
}
}
export async function apiAdminDonationUpdateStatus({
id,
changeStatus,
data,
}: {
id: string;
changeStatus: "publish" | "review" | "reject";
data?: string;
}) {
try {
const response = await apiConfig.put(
`/mobile/admin/donation/${id}?status=${changeStatus}`,
{
data: data,
}
);
return response.data;
} catch (error) {
throw error;
}
}
export async function apiAdminDonationListOfDonatur({
id,
status,
}: {
id: string;
status: "berhasil" | "gagal" | "proses" | "menunggu" | "";
}) {
try {
const response = await apiConfig.get(
`/mobile/admin/donation/${id}/donatur?status=${status}`
);
return response.data;
} catch (error) {
throw error;
}
}

View File

@@ -157,3 +157,14 @@ export async function apiMasterDonation({
throw error;
}
}
// ================== END MASTER DONATION ================== //
export async function apiMasterTransaction() {
try {
const response = await apiConfig.get(`/mobile/master/transaction-status`);
return response.data;
} catch (error) {
throw error;
}
}

View File

@@ -1,6 +1,6 @@
import { MainColor } from "@/constants/color-palet";
import { AccentColor, MainColor } from "@/constants/color-palet";
export const colorBadge = ({ status }: { status: string }) => {
export const colorBadgeStatus = ({ status }: { status: string }) => {
const statusLowerCase = status.toLowerCase();
if (statusLowerCase === "publish") {
return MainColor.green;
@@ -12,3 +12,16 @@ export const colorBadge = ({ status }: { status: string }) => {
return MainColor.placeholder;
}
};
export const colorBadgeTransaction = ({ status }: { status: string }) => {
const statusLowerCase = status.toLowerCase();
if (statusLowerCase === "berhasil") {
return MainColor.green;
} else if (statusLowerCase === "menunggu") {
return MainColor.orange;
} else if (statusLowerCase === "gagal") {
return MainColor.red;
} else {
return AccentColor.blue;
}
};

View File

@@ -0,0 +1,21 @@
import dayjs from "dayjs";
export function countDownAndCondition({
publishTime,
duration,
}: {
publishTime: Date;
duration: number | string;
}) {
const now = dayjs();
const publish = dayjs(publishTime);
const diffTime = publish.diff(now, "day");
const durasi = Number(duration);
const sisaHari = durasi + diffTime;
return {
durationDay: sisaHari,
reminder: sisaHari <= 0,
};
}