From 858b441a8cdeca26247882e13d71a7d24c0b23ac Mon Sep 17 00:00:00 2001 From: bagasbanuna Date: Tue, 2 Dec 2025 17:48:24 +0800 Subject: [PATCH] Clearing apple rejected QC: Inno Fix: - app.config.js - app/(application)/(user)/investment/[id]/index.tsx - app/(application)/(user)/voting/(tabs)/index.tsx - app/(application)/(user)/waiting-room.tsx - app/(application)/terms-agreement.tsx - context/AuthContext.tsx - ios/HIPMIBadungConnect.xcodeproj/project.pbxproj - ios/HIPMIBadungConnect/Info.plist - screens/Authentication/LoginView.tsx - screens/Authentication/VerificationView.tsx - screens/Home/topFeatureSection.tsx - screens/Invesment/BoxBerandaSection.tsx - screens/Invesment/ButtonInvestasiSection.tsx - screens/Invesment/DetailDataPublishSection.tsx - service/api-client/api-voting.ts - service/api-config.ts ### No Issue --- app.config.js | 2 +- .../(user)/investment/[id]/index.tsx | 30 ++++- .../(user)/voting/(tabs)/index.tsx | 3 + app/(application)/(user)/waiting-room.tsx | 22 +++- app/(application)/terms-agreement.tsx | 3 +- context/AuthContext.tsx | 105 +++++++++++++++--- .../project.pbxproj | 4 +- ios/HIPMIBadungConnect/Info.plist | 2 +- screens/Authentication/LoginView.tsx | 39 +++++-- screens/Authentication/VerificationView.tsx | 17 +-- screens/Home/topFeatureSection.tsx | 2 +- screens/Invesment/BoxBerandaSection.tsx | 25 +++-- screens/Invesment/ButtonInvestasiSection.tsx | 5 +- .../Invesment/DetailDataPublishSection.tsx | 2 +- service/api-client/api-voting.ts | 6 +- service/api-config.ts | 8 +- 16 files changed, 203 insertions(+), 72 deletions(-) diff --git a/app.config.js b/app.config.js index 7d324e2..daa473e 100644 --- a/app.config.js +++ b/app.config.js @@ -19,7 +19,7 @@ export default { "NSLocationWhenInUseUsageDescription": "Aplikasi membutuhkan akses lokasi untuk menampilkan peta.", }, associatedDomains: ["applinks:cld-dkr-staging-hipmi.wibudev.com"], - buildNumber: "9", + buildNumber: "10", }, android: { diff --git a/app/(application)/(user)/investment/[id]/index.tsx b/app/(application)/(user)/investment/[id]/index.tsx index 7be9c64..2158182 100644 --- a/app/(application)/(user)/investment/[id]/index.tsx +++ b/app/(application)/(user)/investment/[id]/index.tsx @@ -15,6 +15,7 @@ import Investment_ButtonInvestasiSection from "@/screens/Invesment/ButtonInvesta import Invesment_ComponentBoxOnBottomDetail from "@/screens/Invesment/ComponentBoxOnBottomDetail"; import Invesment_DetailDataPublishSection from "@/screens/Invesment/DetailDataPublishSection"; import { apiInvestmentGetOne } from "@/service/api-client/api-investment"; +import { countDownAndCondition } from "@/utils/countDownAndCondition"; import { AntDesign, MaterialIcons } from "@expo/vector-icons"; import { router, @@ -23,7 +24,7 @@ import { useLocalSearchParams, } from "expo-router"; import _ from "lodash"; -import { useCallback, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; export default function InvestmentDetail() { const { user } = useAuth(); @@ -62,6 +63,31 @@ export default function InvestmentDetail() { setOpenDrawerPublish(false); }; + const [value, setValue] = useState({ + sisa: 0, + reminder: false, + }); + + useEffect(() => { + updateCountDown(); + }, [data]); + + console.log("[DATA DETAIL]", JSON.stringify(data, null, 2)); + + const updateCountDown = () => { + const countDown = countDownAndCondition({ + duration: data?.MasterPencarianInvestor.name, + publishTime: data?.countDown, + }); + + setValue({ + sisa: countDown.durationDay, + reminder: countDown.reminder, + }); + }; + + + const bottomSection = ( + ); return ( diff --git a/app/(application)/(user)/voting/(tabs)/index.tsx b/app/(application)/(user)/voting/(tabs)/index.tsx index f6beef4..0e42863 100644 --- a/app/(application)/(user)/voting/(tabs)/index.tsx +++ b/app/(application)/(user)/voting/(tabs)/index.tsx @@ -6,6 +6,7 @@ import { TextCustom, ViewWrapper, } from "@/components"; +import { useAuth } from "@/hooks/use-auth"; import Voting_BoxPublishSection from "@/screens/Voting/BoxPublishSection"; import { apiVotingGetAll } from "@/service/api-client/api-voting"; import { router, useFocusEffect } from "expo-router"; @@ -13,6 +14,7 @@ import _ from "lodash"; import { useCallback, useState } from "react"; export default function VotingBeranda() { + const { user } = useAuth(); const [listData, setListData] = useState([]); const [loadingGetData, setLoadingGetData] = useState(false); const [search, setSearch] = useState(""); @@ -29,6 +31,7 @@ export default function VotingBeranda() { const response = await apiVotingGetAll({ search, category: "beranda", + userLoginId: user?.id, }); if (response.success) { setListData(response.data); diff --git a/app/(application)/(user)/waiting-room.tsx b/app/(application)/(user)/waiting-room.tsx index 3d2cf16..000020f 100644 --- a/app/(application)/(user)/waiting-room.tsx +++ b/app/(application)/(user)/waiting-room.tsx @@ -4,6 +4,7 @@ import { ButtonCenteredOnly, ButtonCustom, InformationBox, + NewWrapper, StackCustom, ViewWrapper, } from "@/components"; @@ -12,6 +13,7 @@ import { useAuth } from "@/hooks/use-auth"; import { apiUser } from "@/service/api-client/api-user"; import { Ionicons } from "@expo/vector-icons"; import { router } from "expo-router"; +import { RefreshControl } from "react-native"; import Toast from "react-native-toast-message"; export default function WaitingRoom() { @@ -33,7 +35,7 @@ export default function WaitingRoom() { } else { Toast.show({ type: "success", - text1: "Akun anda telah aktif", // text2: "Anda berhasil login", + text1: "Selamat ! Akun anda telah aktif", // text2: "Anda berhasil login", }); router.replace(`/(application)/(user)/profile/create`); } @@ -82,10 +84,18 @@ export default function WaitingRoom() { return ( <> - + + } + > - - + {/* { handleCheck(); @@ -93,9 +103,9 @@ export default function WaitingRoom() { icon="refresh-ccw" > Check - + */} - + ); } diff --git a/app/(application)/terms-agreement.tsx b/app/(application)/terms-agreement.tsx index d07c701..fd869b9 100644 --- a/app/(application)/terms-agreement.tsx +++ b/app/(application)/terms-agreement.tsx @@ -74,7 +74,7 @@ export default function TermsAgreement() { <> @@ -87,6 +87,7 @@ export default function TermsAgreement() { alignItems: "center", marginTop: 16, marginBottom: 16, + paddingInline: 10, }} > setTerm(!term)} /> diff --git a/context/AuthContext.tsx b/context/AuthContext.tsx index 4e14f7b..f2ffd82 100644 --- a/context/AuthContext.tsx +++ b/context/AuthContext.tsx @@ -73,7 +73,22 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => { setIsLoading(true); try { const response = await apiLogin({ nomor: nomor }); - await AsyncStorage.setItem("kode_otp", response.kodeId); + console.log("[RESPONSE AUTH]", JSON.stringify(response)); + + if (response.success) { + Toast.show({ + type: "success", + text1: "Sukses", + text2: "Kode OTP berhasil dikirim", + }); + + await AsyncStorage.setItem("kode_otp", response.kodeId); + router.replace(`/verification?nomor=${nomor}`); + return; + } else { + router.replace(`/register?nomor=${nomor}`); + return; + } } catch (error: any) { throw new Error(error.response?.data?.message || "Gagal kirim OTP"); } finally { @@ -81,13 +96,26 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => { } }; + // const loginWithNomor = async (nomor: string) => { + // setIsLoading(true); + // try { + // const response = await apiLogin({ nomor: nomor }); + // await AsyncStorage.setItem("kode_otp", response.kodeId); + // } catch (error: any) { + // throw new Error(error.response?.data?.message || "Gagal kirim OTP"); + // } finally { + // setIsLoading(false); + // } + // }; + // --- 2. Validasi OTP & cek user --- const validateOtp = async (nomor: string) => { try { setIsLoading(true); const response = await apiValidationCode({ nomor: nomor }); - const { token } = response; + console.log("[RESPONSE VALIDASI OTP]", JSON.stringify(response, null, 2)); + if (response.success) { setToken(token); await AsyncStorage.setItem("authToken", token); @@ -104,20 +132,23 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => { if (response.active) { if (response.roleId === "1") { - return "/(application)/(user)/home"; + router.replace("/(application)/(user)/home"); + return; } else { - return "/(application)/admin/dashboard"; + router.replace("/(application)/admin/dashboard"); + return; } } else { - return "/(application)/(user)/waiting-room"; + router.replace("/(application)/(user)/waiting-room"); + return; } } else { Toast.show({ type: "info", - text1: "Anda belum terdaftar", - text2: "Silahkan daftar terlebih dahulu", + text1: "Terjadi kesalahan", + text2: "Silahkan coba lagi", }); - return `/register?nomor=${nomor}`; + return; } } catch (error: any) { console.log("Error validasi otp >>", (error as Error).message || error); @@ -132,6 +163,10 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => { // --- 3. Ambil data user --- const userData = async (token: string) => { try { + if (!token) { + throw new Error("Token tidak ditemukan"); + } + setIsLoading(true); const response = await apiConfig.get(`/mobile?token=${token}`, { headers: { @@ -145,7 +180,10 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => { await AsyncStorage.setItem("userData", JSON.stringify(dataUser)); return dataUser; } catch (error: any) { - console.log("[LOAD USER DATA]",error.response?.data?.message + "user" || "Gagal mengambil data user"); + console.log( + "[LOAD USER DATA]", + error.response?.data?.message + "user" || "Gagal mengambil data user" + ); } finally { setIsLoading(false); } @@ -160,9 +198,8 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => { setIsLoading(true); try { const response = await apiRegister({ data: userData }); - console.log("response", response); + console.log("[REGISTER FETCH]", JSON.stringify(response, null, 2)); - const { token } = response; if (!response.success) { Toast.show({ type: "info", @@ -173,23 +210,63 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => { return; } - setToken(token); - await AsyncStorage.setItem("authToken", token); Toast.show({ type: "success", text1: "Sukses", text2: "Anda berhasil terdaftar", }); - router.replace("/(application)/(user)/waiting-room"); + router.replace(`/verification?nomor=${userData.nomor}`); return; } catch (error: any) { + Toast.show({ + type: "error", + text1: "Error", + text2: error.response?.data?.message || "Gagal mendaftar", + }); console.log("Error register", error); } finally { setIsLoading(false); } }; + // const registerUser = async (userData: { + // username: string; + // nomor: string; + // termsOfServiceAccepted: boolean; + // }) => { + // setIsLoading(true); + // try { + // const response = await apiRegister({ data: userData }); + // console.log("response", response); + + // const { token } = response; + // if (!response.success) { + // Toast.show({ + // type: "info", + // text1: "Info", + // text2: response.message, + // }); + + // return; + // } + + // setToken(token); + // await AsyncStorage.setItem("authToken", token); + // Toast.show({ + // type: "success", + // text1: "Sukses", + // text2: "Anda berhasil terdaftar", + // }); + // router.replace("/(application)/(user)/waiting-room"); + // return; + // } catch (error: any) { + // console.log("Error register", error); + // } finally { + // setIsLoading(false); + // } + // }; // --- 5. Logout --- + const logout = async () => { try { setIsLoading(true); diff --git a/ios/HIPMIBadungConnect.xcodeproj/project.pbxproj b/ios/HIPMIBadungConnect.xcodeproj/project.pbxproj index 94f5563..c7e28a8 100644 --- a/ios/HIPMIBadungConnect.xcodeproj/project.pbxproj +++ b/ios/HIPMIBadungConnect.xcodeproj/project.pbxproj @@ -422,7 +422,7 @@ ); OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = "com.anonymous.hipmi-mobile"; - PRODUCT_NAME = HIPMIBadungConnect; + PRODUCT_NAME = "HIPMIBadungConnect"; SWIFT_OBJC_BRIDGING_HEADER = "HIPMIBadungConnect/HIPMIBadungConnect-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -454,7 +454,7 @@ ); OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = "com.anonymous.hipmi-mobile"; - PRODUCT_NAME = HIPMIBadungConnect; + PRODUCT_NAME = "HIPMIBadungConnect"; SWIFT_OBJC_BRIDGING_HEADER = "HIPMIBadungConnect/HIPMIBadungConnect-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/ios/HIPMIBadungConnect/Info.plist b/ios/HIPMIBadungConnect/Info.plist index dab20b7..715a448 100644 --- a/ios/HIPMIBadungConnect/Info.plist +++ b/ios/HIPMIBadungConnect/Info.plist @@ -39,7 +39,7 @@ CFBundleVersion - 9 + 10 ITSAppUsesNonExemptEncryption LSMinimumSystemVersion diff --git a/screens/Authentication/LoginView.tsx b/screens/Authentication/LoginView.tsx index 0dfe2ec..7238cd1 100644 --- a/screens/Authentication/LoginView.tsx +++ b/screens/Authentication/LoginView.tsx @@ -72,20 +72,11 @@ export default function LoginView() { const realNumber = callingCode + fixNumber; - console.log("[REALNUMBER]", realNumber); - try { setLoading(true); - // const response = await apiLogin({ nomor: realNumber }); - await loginWithNomor(realNumber); - - Toast.show({ - type: "success", - text1: "Sukses", - text2: "Kode OTP berhasil dikirim", - }); - - router.navigate(`/verification?nomor=${realNumber}`); + const response = await loginWithNomor(realNumber); + console.log("[RESPONSE UI]", response); + } catch (error) { console.log("Error login", error); Toast.show({ @@ -96,6 +87,30 @@ export default function LoginView() { } finally { setLoading(false); } + + // try { + // setLoading(true); + // // const response = await apiLogin({ nomor: realNumber }); + // const response = await loginWithNomor(realNumber); + // console.log("[RESPONSE]", response); + + // Toast.show({ + // type: "success", + // text1: "Sukses", + // text2: "Kode OTP berhasil dikirim", + // }); + + // // router.navigate(`/verification?nomor=${realNumber}`); + // } catch (error) { + // console.log("Error login", error); + // Toast.show({ + // type: "error", + // text1: "Error", + // text2: error as string, + // }); + // } finally { + // setLoading(false); + // } } if (token && token !== "" && !isUserActive) { diff --git a/screens/Authentication/VerificationView.tsx b/screens/Authentication/VerificationView.tsx index 0be0100..37a39e6 100644 --- a/screens/Authentication/VerificationView.tsx +++ b/screens/Authentication/VerificationView.tsx @@ -89,8 +89,9 @@ export default function VerificationView() { // ✅ VERIFIKASI OTOMATIS UNTUK APPLE REVIEW if (inputOtp === "1234") { try { - const response = await validateOtp(nomor as string); - router.replace(response); + await validateOtp(nomor as string); + + return; } catch (error) { console.log("Error verification", error); Toast.show({ type: "error", text1: "Gagal verifikasi" }); @@ -103,16 +104,8 @@ export default function VerificationView() { // 🔁 VERIFIKASI NORMAL (untuk pengguna sungguhan) try { - const response = await validateOtp(nomor as string); - // registerForPushNotificationsAsync().then((token) => { - // if (token) { - // console.log("Expo Push Token:", token); - // // TODO: Kirim token ke backend kamu - // } else { - // console.log("Failed to get Expo Push Token"); - // } - // }); - router.replace(response); + await validateOtp(nomor as string); + return } catch (error) { console.log("Error verification", error); Toast.show({ type: "error", text1: "Gagal verifikasi" }); diff --git a/screens/Home/topFeatureSection.tsx b/screens/Home/topFeatureSection.tsx index 90664c1..8befc82 100644 --- a/screens/Home/topFeatureSection.tsx +++ b/screens/Home/topFeatureSection.tsx @@ -15,7 +15,7 @@ export default function Home_FeatureSection() { name: "Collaboration", icon: , onPress: () => router.push("/(application)/(user)/collaboration/(tabs)"), - status: "active", + status: "inactive", }, { name: "Voting", diff --git a/screens/Invesment/BoxBerandaSection.tsx b/screens/Invesment/BoxBerandaSection.tsx index 0d2bd2d..5e6292a 100644 --- a/screens/Invesment/BoxBerandaSection.tsx +++ b/screens/Invesment/BoxBerandaSection.tsx @@ -1,12 +1,13 @@ /* eslint-disable react-hooks/exhaustive-deps */ import { - BaseBox, - Grid, - ProgressCustom, - StackCustom, - TextCustom, + BaseBox, + Grid, + ProgressCustom, + StackCustom, + TextCustom, } from "@/components"; import API_STRORAGE from "@/constants/base-url-api-strorage"; +import { MainColor } from "@/constants/color-palet"; import DUMMY_IMAGE from "@/constants/dummy-image-value"; import { countDownAndCondition } from "@/utils/countDownAndCondition"; import { Ionicons } from "@expo/vector-icons"; @@ -21,7 +22,7 @@ export default function Investment_BoxBerandaSection({ id: string; data: any; }) { -// console.log("[DATA By one]", JSON.stringify(data, null, 2)); + // console.log("[DATA By one]", JSON.stringify(data, null, 2)); const [value, setValue] = useState({ sisa: 0, @@ -32,6 +33,8 @@ export default function Investment_BoxBerandaSection({ updateCountDown(); }, [data]); + console.log("[DATA BERANDA]", JSON.stringify(data, null, 2)); + const updateCountDown = () => { const countDown = countDownAndCondition({ duration: data?.pencarianInvestor, @@ -66,8 +69,10 @@ export default function Investment_BoxBerandaSection({ {data.title} {value.reminder ? ( - Periode Investasi Berakhir + Periode Berakhir ) : ( - - Sisa waktu: {value.sisa} hari - + Sisa waktu: {value.sisa} hari )} diff --git a/screens/Invesment/ButtonInvestasiSection.tsx b/screens/Invesment/ButtonInvestasiSection.tsx index 355fb5d..7af270f 100644 --- a/screens/Invesment/ButtonInvestasiSection.tsx +++ b/screens/Invesment/ButtonInvestasiSection.tsx @@ -4,9 +4,11 @@ import { router } from "expo-router"; export default function Investment_ButtonInvestasiSection({ id, isMine, + reminder, }: { id: string; isMine: boolean; + reminder: boolean; }) { return ( <> @@ -14,11 +16,12 @@ export default function Investment_ButtonInvestasiSection({ Investasi ini milik Anda ) : ( { router.navigate(`/investment/${id}/(transaction-flow)`); }} > - Beli Saham + {reminder ? "Periode Investasi Berakhir" : "Beli Saham"} )} diff --git a/screens/Invesment/DetailDataPublishSection.tsx b/screens/Invesment/DetailDataPublishSection.tsx index d67b93f..63b12f5 100644 --- a/screens/Invesment/DetailDataPublishSection.tsx +++ b/screens/Invesment/DetailDataPublishSection.tsx @@ -52,7 +52,7 @@ export default function Invesment_DetailDataPublishSection({ )} { @@ -29,16 +28,15 @@ apiConfig.interceptors.request.use( ); export async function apiVersion() { - // console.log("API_BASE_URL", API_BASE_URL); const response = await apiConfig.get("/version"); return response.data; } export async function apiLogin({ nomor }: { nomor: string }) { - const response = await apiConfig.post("/auth/login", { + const response = await apiConfig.post("/mobile/auth/login", { nomor: nomor, }); - return response.data; + return response.data;; } export async function apiCheckCodeOtp({ kodeId }: { kodeId: string }) { @@ -58,7 +56,7 @@ export async function apiRegister({ }: { data: { nomor: string; username: string; termsOfServiceAccepted: boolean }; }) { - const response = await apiConfig.post(`/auth/register`, { + const response = await apiConfig.post(`/mobile/auth/register`, { data: data, }); return response.data;