upd: profile

Deskripsi:
- percobaan fetch profile menggunakan redux
- install package redux

No Issues
This commit is contained in:
amel
2025-04-17 17:29:17 +08:00
parent 043d15bdd9
commit fcad450649
8 changed files with 89 additions and 67 deletions

View File

@@ -4,10 +4,12 @@ import HeaderRightDivisionList from "@/components/division/headerDivisionList";
import HeaderMemberList from "@/components/member/headerMemberList";
import HeaderRightProjectList from "@/components/project/headerProjectList";
import { Headers } from "@/constants/Headers";
import store from "@/lib/store";
import { useAuthSession } from "@/providers/AuthProvider";
import { Redirect, router, Stack } from "expo-router";
import { StatusBar } from 'expo-status-bar';
import { Text } from "react-native";
import { Provider } from "react-redux";
export default function RootLayout() {
const { token, isLoading } = useAuthSession()
@@ -21,7 +23,7 @@ export default function RootLayout() {
}
return (
<>
<Provider store={store}>
<Stack screenOptions={Headers.shadow}>
<Stack.Screen name="home" options={{ title: 'Home' }} />
<Stack.Screen name="feature" options={{ title: 'Fitur' }} />
@@ -57,6 +59,6 @@ export default function RootLayout() {
<Stack.Screen name="division/[id]/(fitur-division)" options={{ headerShown: false }} />
</Stack>
<StatusBar style="light" />
</>
</Provider>
)
}

View File

@@ -3,13 +3,38 @@ import ButtonBackHeader from "@/components/buttonBackHeader";
import { ButtonHeader } from "@/components/buttonHeader";
import ItemDetailMember from "@/components/itemDetailMember";
import Styles from "@/constants/Styles";
import { apiGetProfile } from "@/lib/api";
import { setEntities } from "@/lib/entitiesSlice";
import { useAuthSession } from "@/providers/AuthProvider";
import { Octicons } from "@expo/vector-icons";
import { router, Stack } from "expo-router";
import { useEffect } from "react";
import { Image, SafeAreaView, ScrollView, Text, View } from "react-native";
import { useDispatch, useSelector } from 'react-redux';
export default function Profile() {
const {signOut, token} = useAuthSession()
const { signOut, token } = useAuthSession()
const dispatch = useDispatch()
const entities = useSelector((state: any) => state.entities)
useEffect(() => {
apiGetProfile({ id: 'supadminAmalia' }).then((data) => dispatch(setEntities(data.data)));
}, [dispatch]);
useEffect(() => {
handleUserLogin()
}, []);
function handleUserLogin() {
console.log(token?.current)
var C = require("crypto-js");
var Decrypted = C.AES.decrypt(token?.current, "your password");
var result = Decrypted.toString(C.enc.Utf8);
console.log(result)
}
return (
<SafeAreaView>
@@ -25,8 +50,7 @@ export default function Profile() {
AlertKonfirmasi({
title: 'Keluar',
desc: 'Apakah anda yakin ingin keluar?',
// onPress: () => { router.push('/') }
onPress: () => { signOut()}
onPress: () => { signOut() }
})
}}
/>
@@ -36,23 +60,23 @@ export default function Profile() {
<View style={{ flexDirection: 'column' }}>
<View style={[Styles.wrapHeadViewMember]}>
<Image
source={require("../../assets/images/user.jpeg")}
source={{ uri: `https://wibu-storage.wibudev.com/api/files/${entities.img}` }}
style={[Styles.userProfileBig]}
/>
<Text style={[Styles.textSubtitle, Styles.cWhite, Styles.mt10]}>Putri Ayu Dewi</Text>
<Text style={[Styles.textMediumNormal, Styles.cWhite]}>Super Admin</Text>
<Text style={[Styles.textSubtitle, Styles.cWhite, Styles.mt10]}>{entities.name}</Text>
<Text style={[Styles.textMediumNormal, Styles.cWhite]}>{entities.role}</Text>
</View>
<View style={[Styles.p15]}>
<View style={[Styles.rowSpaceBetween]}>
<Text style={[Styles.textDefaultSemiBold]}>Informasi</Text>
<Text style={[Styles.textLink]}>Edit</Text>
</View>
<ItemDetailMember category="nik" value="123456789" />
<ItemDetailMember category="group" value="Dinas" />
<ItemDetailMember category="position" value="Sekretaris" />
<ItemDetailMember category="phone" value="08980873782" />
<ItemDetailMember category="email" value="putri@gmail.com" />
<ItemDetailMember category="gender" value="Perempuan" />
<ItemDetailMember category="nik" value={entities.nik} />
<ItemDetailMember category="group" value={entities.group} />
<ItemDetailMember category="position" value={entities.position} />
<ItemDetailMember category="phone" value={`0${entities.phone}`} />
<ItemDetailMember category="email" value={entities.email} />
<ItemDetailMember category="gender" value={entities.gender == "F" ? 'Perempuan' : 'Laki-laki'} />
</View>
</View>
</ScrollView>

View File

@@ -7,8 +7,6 @@ import { Text } from "react-native";
export default function Index() {
// const [loadingLogin, setLoadingLogin] = useState(false)
// const [disableLogin, setDisableLogin] = useState(true)
const [isValid, setValid] = useState(false)
const [phone, setPhone] = useState('')
const [otp, setOtp] = useState(0)
@@ -22,55 +20,10 @@ export default function Index() {
return <Redirect href="/home" />;
}
// const handleCheckPhone = async () => {
// try {
// setLoadingLogin(true)
// const response = await apiCheckPhoneLogin({ phone: `62${phone}` });
// if (response.success) {
// const otp = Math.floor(1000 + Math.random() * 9000);
// console.log(otp);
// // return router.push('/verification')
// }
// return ToastAndroid.show(response.message, ToastAndroid.SHORT)
// } catch (error) {
// console.error('Error fetching data:', error);
// return ToastAndroid.show('Terjadi kesalahan', ToastAndroid.SHORT)
// } finally {
// setLoadingLogin(false)
// }
// };
if (isValid) { return <ViewVerification phone={phone} otp={otp} /> }
return (
<>
{/* <View style={Styles.wrapLogin} >
<View style={{ alignItems: "center", marginVertical: 50 }}>
<Image
source={require("../assets/images/splash-icon.png")}
style={{ width: 130, height: 130 }}
/>
<Text style={[Styles.textSubtitle]}>PERBEKEL DARMASABA</Text>
</View>
<InputForm
onChange={(val) => {
val == "" ? setDisableLogin(true) : setDisableLogin(false)
setPhone(val)
}}
type="numeric"
placeholder="XXX-XXX-XXXX"
round
itemLeft={<Text>+62</Text>}
info="Kami akan mengirim kode verifikasi melalui WhatsApp, guna mengonfirmasikan nomor Anda." />
<ButtonForm
text="MASUK"
onPress={() => { handleCheckPhone() }}
disabled={disableLogin}
/>
</View>
{
loadingLogin && <ModalLoading isVisible={true} setVisible={setLoadingLogin} />
} */}
<ViewLogin
onValidate={(val) => {
setPhone(val.phone)

BIN
bun.lockb

Binary file not shown.

View File

@@ -9,16 +9,16 @@ export const apiCheckPhoneLogin = async (body: { phone: string }) => {
return response.data;
}
export const apiSendOtp = async (body: { phone: string, otp:number }) => {
export const apiSendOtp = async (body: { phone: string, otp: number }) => {
const res = await axios.get(`https://wa.wibudev.com/code?nom=${body.phone}&text=*DARMASABA*%0A%0A
JANGAN BERIKAN KODE RAHASIA ini kepada siapa pun TERMASUK PIHAK DARMASABA. Masukkan otentikasi: *${encodeURIComponent(body.otp)}*`)
return res.status
}
// export const getEntities = async () => {
// const response = await axios.get('https://stg-darmasaba.wibudev.com/api/version-app');
// return response.data;
// };
export const apiGetProfile = async ({ id }: { id: string }) => {
const response = await api.get(`/user/${id}`);
return response.data;
};
// export const createEntity = async (newEntity: any) => {
// const response = await api.post('/entities', newEntity);

29
lib/entitiesSlice.ts Normal file
View File

@@ -0,0 +1,29 @@
import { createSlice } from '@reduxjs/toolkit';
const entitiesSlice = createSlice({
name: 'entities',
initialState: {},
reducers: {
setEntities: (state, action) => {
return action.payload;
},
addEntity: (state: any, action: any) => {
state.push(action.payload);
},
updateEntity: (state: any, action) => {
const { id, updatedEntity } = action.payload;
const index = state.findIndex((entity: any) => entity.id === id);
if (index !== -1) {
state[index] = updatedEntity;
}
},
// removeEntity: (state, action) => {
// const idToRemove = action.payload;
// return state.filter((entity: any) => entity.id !== idToRemove);
// },
},
});
export const { setEntities, addEntity, updateEntity } = entitiesSlice.actions;
export default entitiesSlice.reducer;

11
lib/store.ts Normal file
View File

@@ -0,0 +1,11 @@
import { configureStore } from '@reduxjs/toolkit';
import entitiesReducer from './entitiesSlice';
const store = configureStore({
reducer: {
entities: entitiesReducer,
// Add other reducers as needed
},
});
export default store;

View File

@@ -19,6 +19,7 @@
"@react-native-async-storage/async-storage": "^2.1.2",
"@react-navigation/bottom-tabs": "^7.2.0",
"@react-navigation/native": "^7.0.14",
"@reduxjs/toolkit": "^2.7.0",
"axios": "^1.8.4",
"crypto-es": "^2.1.0",
"crypto-js": "^3.1.9-1",
@@ -54,7 +55,9 @@
"react-native-svg": "15.8.0",
"react-native-ui-datepicker": "^3.0.5",
"react-native-web": "~0.19.13",
"react-native-webview": "13.12.5"
"react-native-webview": "13.12.5",
"react-redux": "^9.2.0",
"redux": "^5.0.1"
},
"devDependencies": {
"@babel/core": "^7.25.2",