upd: profile
Deskripsi: - percobaan fetch profile menggunakan redux - install package redux No Issues
This commit is contained in:
@@ -4,10 +4,12 @@ import HeaderRightDivisionList from "@/components/division/headerDivisionList";
|
|||||||
import HeaderMemberList from "@/components/member/headerMemberList";
|
import HeaderMemberList from "@/components/member/headerMemberList";
|
||||||
import HeaderRightProjectList from "@/components/project/headerProjectList";
|
import HeaderRightProjectList from "@/components/project/headerProjectList";
|
||||||
import { Headers } from "@/constants/Headers";
|
import { Headers } from "@/constants/Headers";
|
||||||
|
import store from "@/lib/store";
|
||||||
import { useAuthSession } from "@/providers/AuthProvider";
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
import { Redirect, router, Stack } from "expo-router";
|
import { Redirect, router, Stack } from "expo-router";
|
||||||
import { StatusBar } from 'expo-status-bar';
|
import { StatusBar } from 'expo-status-bar';
|
||||||
import { Text } from "react-native";
|
import { Text } from "react-native";
|
||||||
|
import { Provider } from "react-redux";
|
||||||
|
|
||||||
export default function RootLayout() {
|
export default function RootLayout() {
|
||||||
const { token, isLoading } = useAuthSession()
|
const { token, isLoading } = useAuthSession()
|
||||||
@@ -21,7 +23,7 @@ export default function RootLayout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Provider store={store}>
|
||||||
<Stack screenOptions={Headers.shadow}>
|
<Stack screenOptions={Headers.shadow}>
|
||||||
<Stack.Screen name="home" options={{ title: 'Home' }} />
|
<Stack.Screen name="home" options={{ title: 'Home' }} />
|
||||||
<Stack.Screen name="feature" options={{ title: 'Fitur' }} />
|
<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.Screen name="division/[id]/(fitur-division)" options={{ headerShown: false }} />
|
||||||
</Stack>
|
</Stack>
|
||||||
<StatusBar style="light" />
|
<StatusBar style="light" />
|
||||||
</>
|
</Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,38 @@ import ButtonBackHeader from "@/components/buttonBackHeader";
|
|||||||
import { ButtonHeader } from "@/components/buttonHeader";
|
import { ButtonHeader } from "@/components/buttonHeader";
|
||||||
import ItemDetailMember from "@/components/itemDetailMember";
|
import ItemDetailMember from "@/components/itemDetailMember";
|
||||||
import Styles from "@/constants/Styles";
|
import Styles from "@/constants/Styles";
|
||||||
|
import { apiGetProfile } from "@/lib/api";
|
||||||
|
import { setEntities } from "@/lib/entitiesSlice";
|
||||||
import { useAuthSession } from "@/providers/AuthProvider";
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
import { Octicons } from "@expo/vector-icons";
|
import { Octicons } from "@expo/vector-icons";
|
||||||
import { router, Stack } from "expo-router";
|
import { router, Stack } from "expo-router";
|
||||||
|
import { useEffect } from "react";
|
||||||
import { Image, SafeAreaView, ScrollView, Text, View } from "react-native";
|
import { Image, SafeAreaView, ScrollView, Text, View } from "react-native";
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
|
||||||
export default function Profile() {
|
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 (
|
return (
|
||||||
<SafeAreaView>
|
<SafeAreaView>
|
||||||
@@ -25,8 +50,7 @@ export default function Profile() {
|
|||||||
AlertKonfirmasi({
|
AlertKonfirmasi({
|
||||||
title: 'Keluar',
|
title: 'Keluar',
|
||||||
desc: 'Apakah anda yakin ingin 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={{ flexDirection: 'column' }}>
|
||||||
<View style={[Styles.wrapHeadViewMember]}>
|
<View style={[Styles.wrapHeadViewMember]}>
|
||||||
<Image
|
<Image
|
||||||
source={require("../../assets/images/user.jpeg")}
|
source={{ uri: `https://wibu-storage.wibudev.com/api/files/${entities.img}` }}
|
||||||
style={[Styles.userProfileBig]}
|
style={[Styles.userProfileBig]}
|
||||||
/>
|
/>
|
||||||
<Text style={[Styles.textSubtitle, Styles.cWhite, Styles.mt10]}>Putri Ayu Dewi</Text>
|
<Text style={[Styles.textSubtitle, Styles.cWhite, Styles.mt10]}>{entities.name}</Text>
|
||||||
<Text style={[Styles.textMediumNormal, Styles.cWhite]}>Super Admin</Text>
|
<Text style={[Styles.textMediumNormal, Styles.cWhite]}>{entities.role}</Text>
|
||||||
</View>
|
</View>
|
||||||
<View style={[Styles.p15]}>
|
<View style={[Styles.p15]}>
|
||||||
<View style={[Styles.rowSpaceBetween]}>
|
<View style={[Styles.rowSpaceBetween]}>
|
||||||
<Text style={[Styles.textDefaultSemiBold]}>Informasi</Text>
|
<Text style={[Styles.textDefaultSemiBold]}>Informasi</Text>
|
||||||
<Text style={[Styles.textLink]}>Edit</Text>
|
<Text style={[Styles.textLink]}>Edit</Text>
|
||||||
</View>
|
</View>
|
||||||
<ItemDetailMember category="nik" value="123456789" />
|
<ItemDetailMember category="nik" value={entities.nik} />
|
||||||
<ItemDetailMember category="group" value="Dinas" />
|
<ItemDetailMember category="group" value={entities.group} />
|
||||||
<ItemDetailMember category="position" value="Sekretaris" />
|
<ItemDetailMember category="position" value={entities.position} />
|
||||||
<ItemDetailMember category="phone" value="08980873782" />
|
<ItemDetailMember category="phone" value={`0${entities.phone}`} />
|
||||||
<ItemDetailMember category="email" value="putri@gmail.com" />
|
<ItemDetailMember category="email" value={entities.email} />
|
||||||
<ItemDetailMember category="gender" value="Perempuan" />
|
<ItemDetailMember category="gender" value={entities.gender == "F" ? 'Perempuan' : 'Laki-laki'} />
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import { Text } from "react-native";
|
|||||||
|
|
||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
// const [loadingLogin, setLoadingLogin] = useState(false)
|
|
||||||
// const [disableLogin, setDisableLogin] = useState(true)
|
|
||||||
const [isValid, setValid] = useState(false)
|
const [isValid, setValid] = useState(false)
|
||||||
const [phone, setPhone] = useState('')
|
const [phone, setPhone] = useState('')
|
||||||
const [otp, setOtp] = useState(0)
|
const [otp, setOtp] = useState(0)
|
||||||
@@ -22,55 +20,10 @@ export default function Index() {
|
|||||||
return <Redirect href="/home" />;
|
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} /> }
|
if (isValid) { return <ViewVerification phone={phone} otp={otp} /> }
|
||||||
|
|
||||||
return (
|
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
|
<ViewLogin
|
||||||
onValidate={(val) => {
|
onValidate={(val) => {
|
||||||
setPhone(val.phone)
|
setPhone(val.phone)
|
||||||
|
|||||||
10
lib/api.ts
10
lib/api.ts
@@ -9,16 +9,16 @@ export const apiCheckPhoneLogin = async (body: { phone: string }) => {
|
|||||||
return response.data;
|
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
|
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)}*`)
|
JANGAN BERIKAN KODE RAHASIA ini kepada siapa pun TERMASUK PIHAK DARMASABA. Masukkan otentikasi: *${encodeURIComponent(body.otp)}*`)
|
||||||
return res.status
|
return res.status
|
||||||
}
|
}
|
||||||
|
|
||||||
// export const getEntities = async () => {
|
export const apiGetProfile = async ({ id }: { id: string }) => {
|
||||||
// const response = await axios.get('https://stg-darmasaba.wibudev.com/api/version-app');
|
const response = await api.get(`/user/${id}`);
|
||||||
// return response.data;
|
return response.data;
|
||||||
// };
|
};
|
||||||
|
|
||||||
// export const createEntity = async (newEntity: any) => {
|
// export const createEntity = async (newEntity: any) => {
|
||||||
// const response = await api.post('/entities', newEntity);
|
// const response = await api.post('/entities', newEntity);
|
||||||
|
|||||||
29
lib/entitiesSlice.ts
Normal file
29
lib/entitiesSlice.ts
Normal 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
11
lib/store.ts
Normal 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;
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
"@react-native-async-storage/async-storage": "^2.1.2",
|
"@react-native-async-storage/async-storage": "^2.1.2",
|
||||||
"@react-navigation/bottom-tabs": "^7.2.0",
|
"@react-navigation/bottom-tabs": "^7.2.0",
|
||||||
"@react-navigation/native": "^7.0.14",
|
"@react-navigation/native": "^7.0.14",
|
||||||
|
"@reduxjs/toolkit": "^2.7.0",
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.8.4",
|
||||||
"crypto-es": "^2.1.0",
|
"crypto-es": "^2.1.0",
|
||||||
"crypto-js": "^3.1.9-1",
|
"crypto-js": "^3.1.9-1",
|
||||||
@@ -54,7 +55,9 @@
|
|||||||
"react-native-svg": "15.8.0",
|
"react-native-svg": "15.8.0",
|
||||||
"react-native-ui-datepicker": "^3.0.5",
|
"react-native-ui-datepicker": "^3.0.5",
|
||||||
"react-native-web": "~0.19.13",
|
"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": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.25.2",
|
"@babel/core": "^7.25.2",
|
||||||
|
|||||||
Reference in New Issue
Block a user