Merge pull request 'amalia/27-agustus-25' (#30) from amalia/27-agustus-25 into join

Reviewed-on: bip/mobile-darmasaba#30
This commit is contained in:
2025-08-27 17:34:22 +08:00
10 changed files with 46 additions and 40 deletions

View File

@@ -34,7 +34,7 @@ export default function Index() {
const arrSkeleton = Array.from({ length: 5 }, (_, index) => index)
const [loading, setLoading] = useState(true)
const [status, setStatus] = useState<'true' | 'false'>('true')
const [loadingSubmit, setLoadingSubmit] = useState(false)
const [idChoose, setIdChoose] = useState('')
const [activeChoose, setActiveChoose] = useState(true)
const [titleChoose, setTitleChoose] = useState('')
@@ -49,12 +49,14 @@ export default function Index() {
async function handleEdit() {
try {
setLoadingSubmit(true)
const hasil = await decryptToken(String(token?.current))
const response = await apiEditGroup({ user: hasil, name: titleChoose }, idChoose)
dispatch(setUpdateGroup(!update))
} catch (error) {
console.error(error)
} finally {
setLoadingSubmit(false)
setVisibleEdit(false)
setModal(false)
Toast.show({ type: 'small', text1: 'Berhasil mengupdate data', })
@@ -234,7 +236,7 @@ export default function Index() {
onChange={(val) => { validationForm(val, 'title') }} />
</View>
<View>
<ButtonForm text="SIMPAN" disabled={Object.values(error).some((v) => v == true) || titleChoose == ""} onPress={() => { handleEdit() }} />
<ButtonForm text="SIMPAN" disabled={Object.values(error).some((v) => v == true) || titleChoose == "" || loadingSubmit} onPress={() => { handleEdit() }} />
</View>
</View>
</DrawerBottom>

View File

@@ -22,8 +22,8 @@ import { useDispatch, useSelector } from "react-redux";
export default function Home() {
const entities = useSelector((state: any) => state.entities)
const dispatch = useDispatch()
const { token, decryptToken } = useAuthSession()
const insets = useSafeAreaInsets();
const { token, decryptToken, signOut } = useAuthSession()
const insets = useSafeAreaInsets()
useEffect(() => {
handleUserLogin()
@@ -31,7 +31,11 @@ export default function Home() {
async function handleUserLogin() {
const hasil = await decryptToken(String(token?.current))
apiGetProfile({ id: hasil }).then((data) => dispatch(setEntities(data.data)));
apiGetProfile({ id: hasil })
.then((data) => dispatch(setEntities(data.data)))
.catch((error) => {
signOut()
});
}
return (

View File

@@ -40,6 +40,7 @@ export default function Index() {
const [data, setData] = useState<Props[]>([])
const [search, setSearch] = useState('')
const [nameGroup, setNameGroup] = useState('')
const [loadingSubmit, setLoadingSubmit] = useState(false)
const [chooseData, setChooseData] = useState({ name: '', id: '', active: false, idGroup: '' })
const [error, setError] = useState({
name: false,
@@ -94,15 +95,20 @@ export default function Index() {
async function handleEdit() {
try {
setLoadingSubmit(true)
const hasil = await decryptToken(String(token?.current))
const response = await apiEditPosition({ user: hasil, name: chooseData.name, idGroup: chooseData.idGroup }, chooseData.id)
dispatch(setUpdatePosition(!update))
if (response.success) {
dispatch(setUpdatePosition(!update))
} else {
Toast.show({ type: 'small', text1: response.message, })
}
} catch (error) {
console.error(error)
} finally {
setLoadingSubmit(false)
setVisibleEdit(false)
setModal(false)
Toast.show({ type: 'small', text1: 'Berhasil mengupdate data', })
}
}
@@ -251,7 +257,7 @@ export default function Index() {
/>
</View>
<View style={Styles.mb30}>
<ButtonForm text="SIMPAN" onPress={() => { checkForm() }} />
<ButtonForm text="SIMPAN" onPress={() => { handleEdit() }} disabled={Object.values(error).some((v) => v == true) || chooseData.name == "" || loadingSubmit} />
</View>
</View>
</DrawerBottom>

View File

@@ -1,7 +1,6 @@
import ViewLogin from "@/components/auth/viewLogin";
import ViewVerification from "@/components/auth/viewVerification";
import Text from '@/components/Text';
import ToastCustom from "@/components/toastCustom";
import { requestPermission } from "@/lib/useNotification";
import { useAuthSession } from "@/providers/AuthProvider";
import { Redirect } from "expo-router";

View File

@@ -28,14 +28,13 @@ export default function ViewLogin({ onValidate }: Props) {
const otp = Math.floor(1000 + Math.random() * 9000)
const responseOtp = await apiSendOtp({ phone: `62${phone}`, otp })
if (responseOtp == 200) {
// localStorage.setItem('user', response.id)
await AsyncStorage.setItem('user', response.id);
return onValidate({ phone: `62${phone}`, otp })
}
}
return Toast.show({ type: 'small', text1: response.message, })
return Toast.show({ type: 'small', text1: response.message, position: 'top' })
} catch (error) {
return Toast.show({ type: 'small', text1: 'Terjadi kesalahan', })
return Toast.show({ type: 'small', text1: 'Terjadi kesalahan', position: 'top' })
} finally {
setLoadingLogin(false)
}

View File

@@ -27,7 +27,7 @@ export default function ViewVerification({ phone, otp }: Props) {
const encrypted = await encryptToken(valueUser);
signIn(encrypted);
} else {
return Toast.show({ type: 'small', text1: 'Terjadi kesalahan', })
return Toast.show({ type: 'small', text1: 'Terjadi kesalahan', position: 'top' })
}
}
@@ -35,7 +35,7 @@ export default function ViewVerification({ phone, otp }: Props) {
if (value === otpFix.toString()) {
login()
} else {
return Toast.show({ type: 'small', text1: 'Kode OTP tidak sesuai' });
return Toast.show({ type: 'small', text1: 'Kode OTP tidak sesuai', position: 'top' });
}
}

View File

@@ -43,7 +43,7 @@ export function InputForm({ label, value, placeholder, onChange, info, disable,
round && Styles.round30,
{ backgroundColor: bg && bg == 'white' ? 'white' : 'transparent' },
error && { borderColor: "red" },
Platform.OS == 'ios' && { paddingVertical: 10 },
Platform.OS == 'ios' ? { paddingVertical: 10 } : { paddingVertical: 0 },
]}>
{itemRight != undefined ? itemRight : itemLeft}
<TextInput
@@ -53,7 +53,7 @@ export function InputForm({ label, value, placeholder, onChange, info, disable,
keyboardType={type}
onChangeText={onChange}
placeholderTextColor={'gray'}
style={[Styles.mh05, { width: width ? lebar * width / 100 : lebar * 0.78, color: 'black' }]}
style={[Styles.mh05, { width: width ? lebar * width / 100 : lebar * 0.78, color: 'black' }, Platform.OS == 'ios' ? { paddingVertical: 1 } : { paddingVertical: 5 }]}
/>
</View>
{error && (<Text style={[Styles.textInformation, Styles.cError, Styles.mt05]}>{errorText}</Text>)}
@@ -79,7 +79,7 @@ export function InputForm({ label, value, placeholder, onChange, info, disable,
placeholder={placeholder}
keyboardType={type}
editable={!disable}
style={[Styles.inputRoundForm, error && { borderColor: "red" }, round && Styles.round30, { backgroundColor: bg && bg == 'white' ? 'white' : 'transparent' }, { color: 'black' }, multiline && { height: 150, textAlignVertical: 'top' }]}
style={[Styles.inputRoundForm, Platform.OS == 'ios' ? { paddingVertical: 11 } : { paddingVertical: 6 }, error && { borderColor: "red" }, round && Styles.round30, { backgroundColor: bg && bg == 'white' ? 'white' : 'transparent' }, { color: 'black' }, multiline && { height: 150, textAlignVertical: 'top' }]}
onChangeText={onChange}
placeholderTextColor={'gray'}
multiline={multiline}

View File

@@ -3,7 +3,7 @@ import { apiCreatePosition } from "@/lib/api"
import { setUpdatePosition } from "@/lib/positionSlice"
import { useAuthSession } from "@/providers/AuthProvider"
import { AntDesign } from "@expo/vector-icons"
import { useState } from "react"
import { useEffect, useState } from "react"
import { View } from "react-native"
import Toast from "react-native-toast-message"
import { useDispatch, useSelector } from "react-redux"
@@ -26,6 +26,7 @@ export default function HeaderRightPositionList() {
const [isFilter, setFilter] = useState(false)
const [isSelect, setSelect] = useState(false)
const [choose, setChoose] = useState({ val: '', label: '' })
const [disable, setDisable] = useState(true)
const [dataForm, setDataForm] = useState({
name: "",
idGroup: "",
@@ -54,36 +55,32 @@ export default function HeaderRightPositionList() {
}
function checkAll() {
let nilai = true
let nilai = false
if (dataForm.name == "") {
setError(error => ({ ...error, name: true }))
nilai = false
nilai = true
}
if ((entityUser.role == "supadmin" || entityUser.role == "developer") && (dataForm.idGroup == "" || String(dataForm.idGroup) == "null")) {
setError(error => ({ ...error, idGroup: true }))
nilai = false
nilai = true
}
return nilai
}
function onCheck() {
const check = checkAll()
if (!check)
return false
handleTambah()
setDisable(nilai)
}
useEffect(() => {
checkAll()
}, [dataForm])
async function handleTambah() {
try {
setDisable(true)
const hasil = await decryptToken(String(token?.current))
const response = await apiCreatePosition({ user: hasil, name: dataForm.name, idGroup: dataForm.idGroup })
dispatch(setUpdatePosition(!update))
} catch (error) {
console.error(error)
} finally {
setDisable(false)
setVisibleTambah(false)
setVisible(false)
Toast.show({ type: 'small', text1: 'Berhasil menambahkan data', })
@@ -155,7 +152,10 @@ export default function HeaderRightPositionList() {
/>
</View>
<View style={Styles.mb30}>
<ButtonForm text="SIMPAN" onPress={() => { onCheck() }} />
<ButtonForm
text="SIMPAN"
onPress={() => { handleTambah() }}
disabled={disable} />
</View>
</View>
</DrawerBottom>

View File

@@ -3,9 +3,9 @@ import { View } from "react-native";
import Toast from "react-native-toast-message";
import Text from "./Text";
export default function ToastCustom() {
export default function ToastCustom({ position }: { position?: 'top' | 'bottom' }) {
return (
<Toast autoHide onPress={() => Toast.hide()} visibilityTime={1500} position="bottom" config={{
<Toast autoHide onPress={() => Toast.hide()} visibilityTime={1500} position={position || 'bottom'} config={{
small: ({ text1 }) => (
<View style={[Styles.toastContainer]}>
<Text style={{ fontSize: 12 }}>{text1}</Text>

View File

@@ -138,12 +138,8 @@ export const apiDeletePosition = async (data: { user: string, isActive: boolean
};
export const apiEditPosition = async (data: { user: string, name: string, idGroup: string }, id: string) => {
await api.put(`mobile/position/${id}`, data).then(response => {
return response.data;
})
.catch(error => {
console.error('Error:', error);
});
const response = await api.put(`mobile/position/${id}`, data)
return response.data
};
export const apiGetUser = async ({ user, active, search, group, page }: { user: string, active: string, search: string, group?: string, page?: number }) => {