Add:
- hooks/
- ios.build.device : untuk mendownload di ios

Fix:
- service/api.t : mengatur api
- context/AuthContext.tsx: Provider untuk access token

### No Issue
This commit is contained in:
2025-08-21 15:22:14 +08:00
parent 7a7bfd3ab9
commit 21c6460220
12 changed files with 380 additions and 142 deletions

View File

@@ -1,8 +1,14 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
apiClient,
apiLogin,
apiRegister,
apiValidationCode,
} from "@/service/api";
import { IUser } from "@/types/User";
import { createContext, useEffect, useState } from "react";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { apiClient, apiLogin } from "@/service/api";
import { router } from "expo-router";
import { createContext, useEffect, useState } from "react";
import Toast from "react-native-toast-message";
// --- Types ---
type AuthContextType = {
@@ -13,12 +19,13 @@ type AuthContextType = {
isAdmin: boolean;
isUserActive: boolean;
loginWithNomor: (nomor: string) => Promise<void>;
// validateOtp: (nomor: string, otp: string) => Promise<void>;
// logout: () => Promise<void>;
// registerUser: (userData: {
// username: string;
// nomor: string;
// }) => Promise<void>;
validateOtp: (nomor: string) => Promise<any>;
logout: () => Promise<void>;
registerUser: (userData: {
username: string;
nomor: string;
}) => Promise<void>;
userData: (token: string) => Promise<any>;
};
// --- Create Context ---
@@ -32,7 +39,7 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
const [isLoading, setIsLoading] = useState<boolean>(true);
const isAuthenticated = !!user;
const isAdmin = user?.MasterUserRole?.name === "Admin";
const isAdmin = user?.masterUserRoleId !== "1";
const isUserActive = user?.active === true;
// --- Load session from AsyncStorage on app start ---
@@ -42,6 +49,10 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
const storedToken = await AsyncStorage.getItem("authToken");
const storedUser = await AsyncStorage.getItem("userData");
if (storedToken) {
setToken(storedToken);
}
if (storedToken && storedUser) {
setToken(storedToken);
setUser(JSON.parse(storedUser));
@@ -61,7 +72,8 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
setIsLoading(true);
try {
const response = await apiLogin({ nomor: nomor });
console.log("Response provider login", response);
console.log("Success login api", JSON.stringify(response, null, 2));
await AsyncStorage.setItem("kode_otp", response.kodeId);
} catch (error: any) {
throw new Error(error.response?.data?.message || "Gagal kirim OTP");
} finally {
@@ -69,6 +81,143 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
}
};
// --- 2. Validasi OTP & cek user ---
const validateOtp = async (nomor: string) => {
try {
setIsLoading(true);
const response = await apiValidationCode({ nomor: nomor });
const { token } = response;
if (response.success) {
setToken(token);
await AsyncStorage.setItem("authToken", token);
const responseUser = await apiClient.get(
`/mobile/user?token=${token}`,
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
const dataUser = responseUser.data.data;
console.log("res validasi user :", JSON.stringify(dataUser, null, 2));
setUser(dataUser);
await AsyncStorage.setItem("userData", JSON.stringify(dataUser));
if (response.active) {
if (response.roleId === "1") {
return "/(application)/(user)/home";
} else {
return "/(application)/admin/dashboard";
}
} else {
return "/(application)/(user)/waiting-room";
}
} else {
Toast.show({
type: "info",
text1: "Anda belum terdaftar",
text2: "Silahkan daftar terlebih dahulu",
});
return `/register?nomor=${nomor}`;
}
} catch (error: any) {
console.log("Error validasi otp >>", (error as Error).message || error);
throw new Error(
error.response?.data?.message || "OTP salah atau user tidak ditemukan"
);
} finally {
setIsLoading(false);
}
};
// --- 3. Ambil data user ---
const userData = async (token: string) => {
try {
setIsLoading(true);
const response = await apiClient.get(`/mobile/user?token=${token}`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
const dataUser = response.data.data;
console.log("res validasi user :", JSON.stringify(dataUser, null, 2));
setUser(dataUser);
await AsyncStorage.setItem("userData", JSON.stringify(dataUser));
return dataUser;
} catch (error: any) {
throw new Error(
error.response?.data?.message || "Gagal mengambil data user"
);
} finally {
setIsLoading(false);
}
};
// --- 4. Register jika user belum ada ---
const registerUser = async (userData: {
username: string;
nomor: string;
}) => {
setIsLoading(true);
try {
const response = await apiRegister({ data: userData });
console.log("Success register api", JSON.stringify(response, null, 2));
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);
setToken(null);
setUser(null);
await AsyncStorage.removeItem("authToken");
await AsyncStorage.removeItem("userData");
setIsLoading(false);
Toast.show({
type: "success",
text1: "Logout berhasil",
text2: "Anda berhasil keluar dari akun.",
});
router.replace("/");
} catch (error) {
console.log("Logout error (optional):", error);
} finally {
setIsLoading(false);
}
};
return (
<>
<AuthContext.Provider
@@ -80,9 +229,10 @@ export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
isAdmin,
isUserActive,
loginWithNomor,
// validateOtp,
// logout,
// registerUser,
validateOtp,
logout,
registerUser,
userData,
}}
>
{children}