Files
hipmi-mobile/context/AuthContext.tsx
bagasbanuna d693550a1f Fix Alur Login & Load data forum , user search
Admin – User Access
- app/(application)/admin/user-access/[id]/index.tsx

Authentication
- context/AuthContext.tsx
- screens/Authentication/EULASection.tsx
- screens/Authentication/LoginView.tsx

Forum
- screens/Forum/ViewBeranda3.tsx

Profile & UI Components
- components/Image/AvatarComp.tsx
- screens/Profile/AvatarAndBackground.tsx

### No Issue
2026-01-29 15:08:00 +08:00

294 lines
7.7 KiB
TypeScript

import {
apiConfig,
apiLogin,
apiRegister,
apiUpdatedTermCondition,
apiValidationCode,
} from "@/service/api-config";
import { apiDeviceTokenDeleted } from "@/service/api-device-token";
import { IUser } from "@/types/User";
import AsyncStorage from "@react-native-async-storage/async-storage";
import * as Device from "expo-device";
import { router } from "expo-router";
import { createContext, useEffect, useState } from "react";
import Toast from "react-native-toast-message";
// --- Types ---
type AuthContextType = {
user: IUser | null;
token: string | null;
isLoading: boolean;
isAuthenticated: boolean;
isAdmin: boolean;
isUserActive: boolean;
loginWithNomor: (nomor: string) => Promise<boolean>;
validateOtp: (nomor: string) => Promise<any>;
logout: () => Promise<void>;
registerUser: (userData: {
username: string;
nomor: string;
termsOfServiceAccepted: boolean;
}) => Promise<void>;
userData: (token: string) => Promise<any>;
acceptedTerms: (
nomor: string,
onSetModalVisible: (visible: boolean) => void,
) => Promise<any>;
};
// --- Create Context ---
export const AuthContext = createContext<AuthContextType | undefined>(
undefined,
);
export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
const [user, setUser] = useState<IUser | null>(null);
const [token, setToken] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState<boolean>(true);
const isAuthenticated = !!user;
const isAdmin = user?.masterUserRoleId !== "1";
const isUserActive = user?.active === true;
// --- Load session from AsyncStorage on app start ---
useEffect(() => {
const loadSession = async () => {
try {
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));
}
} catch (error) {
console.error("Failed to load session", error);
} finally {
setIsLoading(false);
}
};
loadSession();
}, []);
// --- 1. Kirim nomor → dapat OTP ---
const loginWithNomor = async (nomor: string) => {
setIsLoading(true);
try {
const response = await apiLogin({ nomor: nomor });
console.log("[RESPONSE AUTH]", JSON.stringify(response, null, 2));
if (response.success && response.isAcceptTerms) {
await AsyncStorage.setItem("kode_otp", response.kodeId);
router.push(`/verification?nomor=${nomor}`);
return true;
} else {
return false;
}
} 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);
const responseUser = await apiConfig.get(`/mobile?token=${token}`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
const dataUser = responseUser.data.data;
setUser(dataUser);
await AsyncStorage.setItem("userData", JSON.stringify(dataUser));
if (response.active) {
// if (response.roleId === "1") {
// router.replace("/(application)/(user)/home");
// return;
// } else {
// router.replace("/(application)/admin/dashboard");
// return;
// }
router.replace("/(application)/(user)/home");
return;
} else {
router.replace("/(application)/(user)/waiting-room");
return;
}
} else {
Toast.show({
type: "info",
text1: "Terjadi kesalahan",
text2: "Silahkan coba lagi",
});
return;
}
} 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 {
if (!token) {
throw new Error("Token tidak ditemukan");
}
setIsLoading(true);
const response = await apiConfig.get(`/mobile?token=${token}`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
const dataUser = response.data.data;
setUser(dataUser);
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",
);
} finally {
setIsLoading(false);
}
};
// --- 4. Register jika user belum ada ---
const registerUser = async (userData: {
username: string;
nomor: string;
termsOfServiceAccepted: boolean;
}) => {
setIsLoading(true);
try {
const response = await apiRegister({ data: userData });
if (!response.success) {
Toast.show({
type: "info",
text1: "Info",
text2: response.message,
});
return;
}
Toast.show({
type: "success",
text1: "Sukses",
text2: "Anda berhasil terdaftar",
});
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);
}
};
// --- 5. Logout ---
const logout = async () => {
try {
setIsLoading(true);
setToken(null);
setUser(null);
const deviceId =
Device.osInternalBuildId || Device.modelName || "unknown";
await AsyncStorage.removeItem("authToken");
await AsyncStorage.removeItem("userData");
await apiDeviceTokenDeleted({ userId: user?.id as any, deviceId });
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);
}
};
// --- 6. Accept Terms ---
const acceptedTerms = async (
nomor: string,
onSetModalVisible: (visible: boolean) => void,
) => {
try {
setIsLoading(true);
const response = await apiUpdatedTermCondition({ nomor: nomor });
if (response.success) {
return `/verification?nomor=${nomor}`;
} else {
return `/register?nomor=${nomor}`;
}
} catch (error) {
console.log("Error accept terms", error);
} finally {
setIsLoading(false);
onSetModalVisible(false);
}
};
return (
<>
<AuthContext.Provider
value={{
user,
token,
isLoading,
isAuthenticated,
isAdmin,
isUserActive,
loginWithNomor,
validateOtp,
logout,
registerUser,
userData,
acceptedTerms,
}}
>
{children}
</AuthContext.Provider>
</>
);
};