From 2be4afdcb11e49d20bedb51037239aa89cd917be Mon Sep 17 00:00:00 2001 From: Bagasbanuna02 Date: Thu, 2 Oct 2025 17:29:25 +0800 Subject: [PATCH] Investment Add: - components/Button/CoyButton.tsx - constants/local-storage-key.ts Fix: - Integrasi pada proses transaksi pmebelian investasi ### No Issue --- .../(user)/investment/(tabs)/transaction.tsx | 162 +++++++++++------- .../[id]/(transaction-flow)/index.tsx | 31 +++- .../[id]/(transaction-flow)/invoice.tsx | 151 ++++++++++++++-- .../[id]/(transaction-flow)/process.tsx | 15 +- .../[id]/(transaction-flow)/select-bank.tsx | 90 ++++++++-- .../(user)/investment/[id]/edit.tsx | 6 +- .../(user)/investment/create.tsx | 7 +- components/Button/CoyButton.tsx | 72 ++++++++ constants/local-storage-key.ts | 4 + .../investment/dummy-data-not-publish.ts | 10 +- service/api-client/api-investment.ts | 64 +++++++ service/api-client/api-master.ts | 15 +- 12 files changed, 514 insertions(+), 113 deletions(-) create mode 100644 components/Button/CoyButton.tsx create mode 100644 constants/local-storage-key.ts diff --git a/app/(application)/(user)/investment/(tabs)/transaction.tsx b/app/(application)/(user)/investment/(tabs)/transaction.tsx index bf8d5ac..ff3bca8 100644 --- a/app/(application)/(user)/investment/(tabs)/transaction.tsx +++ b/app/(application)/(user)/investment/(tabs)/transaction.tsx @@ -1,81 +1,123 @@ +/* eslint-disable react-hooks/exhaustive-deps */ import { BadgeCustom, BaseBox, Grid, + LoaderCustom, StackCustom, TextCustom, ViewWrapper, } from "@/components"; -import { dummyMasterStatusTransaction } from "@/lib/dummy-data/_master/status-transaction"; +import { useAuth } from "@/hooks/use-auth"; +import { apiInvestmentGetInvoice } from "@/service/api-client/api-investment"; import { GStyles } from "@/styles/global-styles"; -import dayjs from "dayjs"; -import { router } from "expo-router"; +import { formatChatTime } from "@/utils/formatChatTime"; +import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay"; +import { router, useFocusEffect } from "expo-router"; +import _ from "lodash"; +import { useCallback, useState } from "react"; import { View } from "react-native"; export default function InvestmentTransaction() { - const randomStatusData = Array.from({ length: 10 }, () => { - const randomIndex = Math.floor( - Math.random() * dummyMasterStatusTransaction.length - ); - return dummyMasterStatusTransaction[randomIndex]; - }); + const { user } = useAuth(); + const [list, setList] = useState([]); + const [loadList, setLoadList] = useState(false); - const handlePress = (value: string) => { - if (value === "menunggu") { - router.push(`/investment/${value}/(transaction-flow)/invoice`); - } else if (value === "proses") { - router.push(`/investment/${value}/(transaction-flow)/process`); - } else if (value === "berhasil") { - router.push(`/investment/${value}/(transaction-flow)/success`); - } else if (value === "gagal") { - router.push(`/investment/${value}/(transaction-flow)/failed`); + useFocusEffect( + useCallback(() => { + onLoadList(); + }, [user?.id]) + ); + + const onLoadList = async () => { + try { + setLoadList(true); + const response = await apiInvestmentGetInvoice({ + authorId: user?.id as string, + category: "transaction", + }); + console.log("[RESPONSE LIST]", JSON.stringify(response.data, null, 2)); + setList(response.data); + } catch (error) { + console.log("[ERROR]", error); + } finally { + setLoadList(false); + } + }; + + 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 = ({ id, status }: { id: string; status: string }) => { + if (status === "menunggu") { + router.push(`/investment/${id}/(transaction-flow)/invoice`); + } else if (status === "proses") { + router.push(`/investment/${id}/(transaction-flow)/process`); + } else if (status === "berhasil") { + router.push(`/investment/${id}/(transaction-flow)/success`); + } else if (status === "gagal") { + router.push(`/investment/${id}/(transaction-flow)/failed`); } }; return ( - {randomStatusData.map((item, i) => ( - { - handlePress(item.value); - }} - > - - - - - Title Investment: Lorem ipsum dolor sit amet consectetur - adipisicing elit. Am culpa excepturi deleniti soluta animi - porro amet ducimus. - - - {dayjs().format("DD/MM/YYYY")} - - - - - - - - - - Rp. 7.500.000 - - - {item.label} - - - - - - ))} + {loadList ? ( + + ) : _.isEmpty(list) ? ( + Tidak ada data + ) : ( + list.map((item: any, i: number) => ( + { + handlePress({ + id: item.id, + status: _.lowerCase(item.statusInvoice), + }); + }} + > + + + + {item?.title || "-"} + + {formatChatTime(item?.createdAt)} + + + + + + + + + + Rp. {formatCurrencyDisplay(item?.nominal) || "-"} + + + {item?.statusInvoice || "-"} + + + + + + )) + )} ); } diff --git a/app/(application)/(user)/investment/[id]/(transaction-flow)/index.tsx b/app/(application)/(user)/investment/[id]/(transaction-flow)/index.tsx index 4f2f268..a3f2494 100644 --- a/app/(application)/(user)/investment/[id]/(transaction-flow)/index.tsx +++ b/app/(application)/(user)/investment/[id]/(transaction-flow)/index.tsx @@ -10,8 +10,10 @@ import { TextInputCustom, ViewWrapper, } from "@/components"; +import { LOCAL_STORAGE_KEY } from "@/constants/local-storage-key"; import { apiInvestmentGetOne } from "@/service/api-client/api-investment"; import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay"; +import AsyncStorage from "@react-native-async-storage/async-storage"; import { router, useFocusEffect, useLocalSearchParams } from "expo-router"; import { useCallback, useState } from "react"; @@ -19,9 +21,10 @@ export default function InvestmentInvest() { const { id } = useLocalSearchParams(); // console.log("[ID]", id); const [data, setData] = useState(null); - const [value, setValue] = useState(0); + const [jumlah, setJumlah] = useState(0); const [total, setTotal] = useState(0); const [sisaLembar, setSisaLembar] = useState(0); + const [isLoading, setIsLoading] = useState(false); useFocusEffect( useCallback(() => { @@ -45,7 +48,7 @@ export default function InvestmentInvest() { const handleTextChange = (text: string) => { // Izinkan input kosong → anggap sebagai 0 (atau abaikan, tergantung UX) if (text === "") { - setValue(0); + setJumlah(0); setTotal(0); return; } @@ -58,7 +61,7 @@ export default function InvestmentInvest() { // Karena regex sudah pastikan hanya angka, isNaN biasanya false // Tapi tetap aman untuk cek if (!isNaN(numValue)) { - setValue(numValue); + setJumlah(numValue); setTotal(numValue * Number(data?.hargaLembar)); console.log("[VALUE]", numValue); } @@ -71,10 +74,24 @@ export default function InvestmentInvest() { <> = sisaLembar} - onPress={() => router.push(`/investment/${id}/select-bank`)} + isLoading={isLoading} + disabled={jumlah < 10 || jumlah > sisaLembar} + onPress={async () => { + try { + setIsLoading(true); + await AsyncStorage.setItem( + LOCAL_STORAGE_KEY.transactionInvestment, + JSON.stringify({ jumlah, total }) + ); + router.push(`/investment/${id}/select-bank`); + } catch (error) { + console.log("[ERROR]", error); + } finally { + setIsLoading(false); + } + }} > - Beli {value}, {sisaLembar} + Beli @@ -126,7 +143,7 @@ export default function InvestmentInvest() { }} placeholder="0" keyboardType="numeric" - value={value.toString()} + value={jumlah.toString()} onChangeText={(value) => { handleTextChange(value); }} diff --git a/app/(application)/(user)/investment/[id]/(transaction-flow)/invoice.tsx b/app/(application)/(user)/investment/[id]/(transaction-flow)/invoice.tsx index 6ce95c7..e76a5a1 100644 --- a/app/(application)/(user)/investment/[id]/(transaction-flow)/invoice.tsx +++ b/app/(application)/(user)/investment/[id]/(transaction-flow)/invoice.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ import { BaseBox, ButtonCenteredOnly, @@ -9,11 +10,96 @@ import { TextCustom, ViewWrapper, } from "@/components"; +import CopyButton from "@/components/Button/CoyButton"; import { MainColor } from "@/constants/color-palet"; -import { router, useLocalSearchParams } from "expo-router"; +import DIRECTORY_ID from "@/constants/directory-id"; +import { + apiInvestmentGetInvoice, + apiInvestmentUpdateInvoice, +} from "@/service/api-client/api-investment"; +import { uploadFileService } from "@/service/upload-service"; +import { formatCurrencyDisplay } from "@/utils/formatCurrencyDisplay"; +import pickFile, { IFileData } 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 InvestmentInvoice() { const { id } = useLocalSearchParams(); + console.log("[ID]", id); + const [data, setData] = useState({}); + const [image, setImage] = useState({ + name: "", + uri: "", + size: 0, + }); + const [isLoading, setIsLoading] = useState(false); + + useFocusEffect( + useCallback(() => { + onLoadData(); + }, [id]) + ); + + const onLoadData = async () => { + try { + const response = await apiInvestmentGetInvoice({ + id: id as string, + category: "invoice", + }); + + console.log("[RES INVOICE]", JSON.stringify(response.data, null, 2)); + setData(response.data); + } catch (error) { + console.log("[ERROR]", error); + } + }; + + const handlerSubmitUpdate = async () => { + try { + setIsLoading(true); + const responseUploadImage = await uploadFileService({ + dirId: DIRECTORY_ID.investasi_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 response = await apiInvestmentUpdateInvoice({ + id: id as string, + data: { + imageId: responseUploadImage?.data?.id, + }, + status: "proses", + }); + + if (response.success) { + console.log( + "[RESPONSE UPDATE]", + JSON.stringify(response.data, null, 2) + ); + Toast.show({ + type: "success", + text1: "Berhasil mengunggah bukti transfer", + }); + router.push(`/investment/${id}/(transaction-flow)/process`); + } + } catch (error) { + console.log("[ERROR]", error); + } finally { + setIsLoading(false); + } + }; + return ( <> @@ -21,9 +107,23 @@ export default function InvestmentInvoice() { - Nama BANK - Nama Penerima + + + Bank + + + {data?.MasterBank?.namaBank} + + + + + Nama Akun + + + {data?.MasterBank?.namaAkun} + + @@ -34,7 +134,7 @@ export default function InvestmentInvoice() { }} > - 4567898765433567 + {data?.MasterBank?.norek} - Salin + @@ -65,7 +165,7 @@ export default function InvestmentInvoice() { }} > - Rp. 1.000.000 + Rp. {formatCurrencyDisplay(data?.nominal)} - Salin + @@ -83,10 +183,37 @@ export default function InvestmentInvoice() { - Upload bukti transfer anda. + + Upload bukti transfer anda. + + {image ? ( + + + {image?.name} + + + ) : ( + + Tidak ada gambar yang diunggah + + )} { - router.push("/(application)/(image)/take-picture/123"); + pickFile({ + allowedType: "image", + setImageUri(file: any) { + console.log("[IMAGE]", file); + setImage(file); + }, + }); }} icon="upload" > @@ -96,14 +223,16 @@ export default function InvestmentInvoice() { { - router.push(`/investment/${id}/(transaction-flow)/process`); + handlerSubmitUpdate(); }} > Saya Sudah Transfer - + ); diff --git a/app/(application)/(user)/investment/[id]/(transaction-flow)/process.tsx b/app/(application)/(user)/investment/[id]/(transaction-flow)/process.tsx index f541987..e277680 100644 --- a/app/(application)/(user)/investment/[id]/(transaction-flow)/process.tsx +++ b/app/(application)/(user)/investment/[id]/(transaction-flow)/process.tsx @@ -1,12 +1,10 @@ import { BaseBox, - Grid, StackCustom, TextCustom, - ViewWrapper, + ViewWrapper } from "@/components"; import { MainColor } from "@/constants/color-palet"; -import { Ionicons } from "@expo/vector-icons"; import { ActivityIndicator } from "react-native"; export default function InvestmentProcess() { @@ -16,21 +14,22 @@ export default function InvestmentProcess() { - Admin sedang memproses transaksi investasimu + Admin sedang memvalidasi data dan bukti transfer anda. Mohon + tunggu proses ini selesai. - + {/* - + Hubungi admin jika tidak kunjung di proses! Klik pada logo Whatsapp ini. - + - + */} ); diff --git a/app/(application)/(user)/investment/[id]/(transaction-flow)/select-bank.tsx b/app/(application)/(user)/investment/[id]/(transaction-flow)/select-bank.tsx index 04c5863..9deb392 100644 --- a/app/(application)/(user)/investment/[id]/(transaction-flow)/select-bank.tsx +++ b/app/(application)/(user)/investment/[id]/(transaction-flow)/select-bank.tsx @@ -5,35 +5,97 @@ import { ViewWrapper, } from "@/components"; import { RadioCustom, RadioGroup } from "@/components/Radio/RadioCustom"; -import { dummyMasterBank } from "@/lib/dummy-data/_master/bank"; +import { LOCAL_STORAGE_KEY } from "@/constants/local-storage-key"; +import { useAuth } from "@/hooks/use-auth"; +import { apiInvestmentCreateInvoice } from "@/service/api-client/api-investment"; +import { apiMasterBank } from "@/service/api-client/api-master"; +import AsyncStorage from "@react-native-async-storage/async-storage"; import { router, useLocalSearchParams } from "expo-router"; -import { useState } from "react"; +import _ from "lodash"; +import { useEffect, useState } from "react"; export default function InvestmentSelectBank() { + const { user } = useAuth(); const { id } = useLocalSearchParams(); - const [value, setValue] = useState(""); + const [select, setSelect] = useState(""); + const [listBank, setListBank] = useState([]); + const [isLoading, setIsLoading] = useState(false); + + useEffect(() => { + loadListBank(); + }, []); + + const loadListBank = async () => { + try { + const response = await apiMasterBank(); + + setListBank(response.data); + } catch (error) { + console.log("[ERROR]", error); + setListBank([]); + } + }; + + const handlerSubmit = async () => { + try { + setIsLoading(true); + const dataCheckout = await AsyncStorage.getItem( + LOCAL_STORAGE_KEY.transactionInvestment + ); + if (dataCheckout) { + const storage = JSON.parse(dataCheckout); + const newData = { + ...storage, + bankId: select, + authorId: user?.id, + }; + + const response = await apiInvestmentCreateInvoice({ + id: id as string, + data: newData, + }); + + if (response.success) { + console.log("[RESPONSE >>]", response); + const invoiceId = response.data.id; + + const delStorage = await AsyncStorage.removeItem( + LOCAL_STORAGE_KEY.transactionInvestment + ); + + console.log("[DEL STORAGE]", delStorage); + router.replace(`/investment/${invoiceId}/invoice`); + } else { + console.log("[FAILED]", response); + } + } + } catch (error) { + console.log("[ERROR]", error); + } finally { + setIsLoading(false); + } + }; const buttonSubmit = () => { return ( <> - router.replace(`/investment/${id}/invoice`)} - > - Pilih - + handlerSubmit()}>Pilih ); }; + return ( - - {dummyMasterBank.map((item) => ( - - - - ))} + + {_.isEmpty(listBank) + ? [] + : listBank?.map((item: any) => ( + + + + ))} ); diff --git a/app/(application)/(user)/investment/[id]/edit.tsx b/app/(application)/(user)/investment/[id]/edit.tsx index eba1dae..3475d27 100644 --- a/app/(application)/(user)/investment/[id]/edit.tsx +++ b/app/(application)/(user)/investment/[id]/edit.tsx @@ -101,9 +101,8 @@ export default function InvestmentEdit() { const displayTargetDana = formatCurrencyDisplay(data?.targetDana); const displayHargaPerLembar = formatCurrencyDisplay(data?.hargaLembar); - const displayTotalLembar = formatCurrencyDisplay( - Number(data?.targetDana) / Number(data?.hargaLembar) - ); + const realTotalLembar = Number(data?.targetDana) / Number(data?.hargaLembar); + const displayTotalLembar = formatCurrencyDisplay(realTotalLembar); const handleChangeCurrency = (field: keyof typeof data) => (text: string) => { const numeric = text.replace(/\D/g, ""); @@ -134,6 +133,7 @@ export default function InvestmentEdit() { const handleSubmitUpdate = async () => { let newData = { ...data, + totalLembar: realTotalLembar.toString(), }; if (!validateData()) { diff --git a/app/(application)/(user)/investment/create.tsx b/app/(application)/(user)/investment/create.tsx index bfab43a..ca64b6b 100644 --- a/app/(application)/(user)/investment/create.tsx +++ b/app/(application)/(user)/investment/create.tsx @@ -74,9 +74,8 @@ export default function InvestmentCreate() { const displayTargetDana = formatCurrencyDisplay(data.targetDana); const displayHargaPerLembar = formatCurrencyDisplay(data.hargaPerLembar); - const displayTotalLembar = formatCurrencyDisplay( - Number(data.targetDana) / Number(data.hargaPerLembar) - ); + const realTotalLembar = Number(data.targetDana) / Number(data.hargaPerLembar); + const displayTotalLembar = formatCurrencyDisplay(realTotalLembar); const handleChangeCurrency = (field: keyof typeof data) => (text: string) => { const numeric = text.replace(/\D/g, ""); @@ -150,7 +149,7 @@ export default function InvestmentCreate() { title: data.title, targetDana: data.targetDana, hargaLembar: data.hargaPerLembar, - totalLembar: displayTotalLembar, + totalLembar: realTotalLembar.toString(), roi: data.rasioKeuntungan, masterPencarianInvestorId: data.pencarianInvestor, masterPembagianDevidenId: data.pembagianDeviden, diff --git a/components/Button/CoyButton.tsx b/components/Button/CoyButton.tsx new file mode 100644 index 0000000..3b4827d --- /dev/null +++ b/components/Button/CoyButton.tsx @@ -0,0 +1,72 @@ +import React, { useState } from "react"; +import { TouchableOpacity, Text, StyleSheet } from "react-native"; +import * as Clipboard from "expo-clipboard"; +import { MainColor } from "@/constants/color-palet"; + +interface CopyButtonProps { + textToCopy: string; + copyLabel?: string; // Teks tombol saat normal, default: "Copy" + copiedLabel?: string; // Teks tombol saat berhasil, default: "Copied!" + onCopySuccess?: () => void; // Callback opsional saat berhasil menyalin + duration?: number; // Durasi (ms) menampilkan "Copied!", default: 2000 + style?: any; // Gaya tambahan untuk tombol + textStyle?: any; // Gaya tambahan untuk teks +} + +const CopyButton: React.FC = ({ + textToCopy, + copyLabel = "Copy", + copiedLabel = "Copied!", + onCopySuccess, + duration = 2000, + style, + textStyle, +}) => { + const [isCopied, setIsCopied] = useState(false); + + const handleCopy = async () => { + try { + await Clipboard.setStringAsync(textToCopy); + setIsCopied(true); + onCopySuccess?.(); + + // Reset kembali ke label "Copy" setelah durasi tertentu + setTimeout(() => { + setIsCopied(false); + }, duration); + } catch (error) { + console.error("Failed to copy text:", error); + // Opsional: tampilkan error toast jika diperlukan + } + }; + + return ( + + + {isCopied ? copiedLabel : copyLabel} + + + ); +}; + +const styles = StyleSheet.create({ + button: { + backgroundColor: MainColor.yellow, + paddingHorizontal: 16, + paddingVertical: 8, + borderRadius: 50, + alignItems: "center", + justifyContent: "center", + }, + text: { + color: MainColor.darkblue, + fontWeight: "600", + fontSize: 14, + }, +}); + +export default CopyButton; diff --git a/constants/local-storage-key.ts b/constants/local-storage-key.ts new file mode 100644 index 0000000..fd81588 --- /dev/null +++ b/constants/local-storage-key.ts @@ -0,0 +1,4 @@ +export const LOCAL_STORAGE_KEY = { + transactionInvestment: "transactionInvestment", + transactionDonation: "transactionDonation", +}; diff --git a/lib/dummy-data/investment/dummy-data-not-publish.ts b/lib/dummy-data/investment/dummy-data-not-publish.ts index 82c2314..b5a5b6c 100644 --- a/lib/dummy-data/investment/dummy-data-not-publish.ts +++ b/lib/dummy-data/investment/dummy-data-not-publish.ts @@ -17,15 +17,15 @@ const listDataNotPublishInvesment = ({ data }: { data: any }) => [ }, { label: "Total Lembar", - value: data?.totalLembar || "-", + value: formatCurrencyDisplay(data?.totalLembar) || "-", }, { label: "Pencarian Investor", - value: data && data?.MasterPencarianInvestor?.name + " hari" || "-", + value: (data && data?.MasterPencarianInvestor?.name + " hari") || "-", }, { label: "Jadwal Pembagian", - value: data && data?.MasterPembagianDeviden?.name + " bulan" || "-", + value: (data && data?.MasterPembagianDeviden?.name + " bulan") || "-", }, { label: "Pembagian Deviden", @@ -52,11 +52,11 @@ const listDataPublishInvesment = ({ data }: { data: any }) => [ }, { label: "Total Lembar", - value: data?.totalLembar || "-", + value: formatCurrencyDisplay(data?.totalLembar) || "-", }, { label: "Sisa Lembar", - value: data?.sisaLembar || "-", + value: formatCurrencyDisplay(data?.sisaLembar) || "-", }, { label: "Pencarian Investor", diff --git a/service/api-client/api-investment.ts b/service/api-client/api-investment.ts index e507e8b..661a7da 100644 --- a/service/api-client/api-investment.ts +++ b/service/api-client/api-investment.ts @@ -137,3 +137,67 @@ export async function apiInvestmentGetAll() { } } +export async function apiInvestmentCreateInvoice({ + id, + data, +}: { + id: string; + data: any; +}) { + try { + const response = await apiConfig.post( + `/mobile/investment/${id}/invoice`, + { + data: data, + } + ); + return response.data; + } catch (error) { + throw error; + } +} + +export async function apiInvestmentGetInvoice({ + id, + authorId, + category, +}: { + id?: string; + authorId?: string; + category: "my-invest" | "transaction" | "invoice"; +}) { + const categoryQuery = `?category=${category}`; + const authorIdQuery = authorId ? `&authorId=${authorId}` : ""; + try { + const response = await apiConfig.get( + `/mobile/investment/${id}/invoice${categoryQuery}${authorIdQuery}` + ); + return response.data; + } catch (error) { + throw error; + } +} + +export async function apiInvestmentUpdateInvoice({ + id, + data, + status, +}: { + id: string; + data: { + imageId?: string; + }; + status: "berhasil" | "gagal" | "proses" | "menunggu"; +}) { + try { + const response = await apiConfig.put( + `/mobile/investment/${id}/invoice?status=${status}`, + { + data: data, + } + ); + return response.data; + } catch (error) { + throw error; + } +} diff --git a/service/api-client/api-master.ts b/service/api-client/api-master.ts index c54aa35..35cb0f6 100644 --- a/service/api-client/api-master.ts +++ b/service/api-client/api-master.ts @@ -110,7 +110,11 @@ export async function apiForumCreateReportCommentar({ export async function apiMasterInvestment({ category, }: { - category?: "pencarian-investor" | "periode-deviden" | "pembagian-deviden" | string; + category?: + | "pencarian-investor" + | "periode-deviden" + | "pembagian-deviden" + | string; }) { const selectCategory = category ? `?category=${category}` : ""; try { @@ -122,3 +126,12 @@ export async function apiMasterInvestment({ throw error; } } + +export async function apiMasterBank() { + try { + const response = await apiConfig.get(`/mobile/master/bank`); + return response.data; + } catch (error) { + throw error; + } +}