Files
mobile-darmasaba/app/(application)/member/edit/[id].tsx
amaliadwiy c230e0b18b upd: custom header
Deskripsi:
- update custom button header

- yg blm : fitur divisi dan yg ada di divisi

No Issues
2026-01-27 17:39:54 +08:00

437 lines
15 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import AppHeader from "@/components/AppHeader";
import ButtonSaveHeader from "@/components/buttonSaveHeader";
import { InputForm } from "@/components/inputForm";
import ModalSelect from "@/components/modalSelect";
import SelectForm from "@/components/selectForm";
import Text from "@/components/Text";
import { ConstEnv } from "@/constants/ConstEnv";
import Styles from "@/constants/Styles";
import { apiEditUser, apiGetProfile } from "@/lib/api";
import { validateName } from "@/lib/fun_validateName";
import { setUpdateMember } from "@/lib/memberSlice";
import { useAuthSession } from "@/providers/AuthProvider";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import { useHeaderHeight } from '@react-navigation/elements';
import * as ImagePicker from "expo-image-picker";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import {
Image,
KeyboardAvoidingView,
Platform,
Pressable,
SafeAreaView,
ScrollView,
View
} from "react-native";
import Toast from "react-native-toast-message";
import { useDispatch, useSelector } from "react-redux";
type Props = {
id: string;
name: string;
nik: string;
email: string;
phone: string;
gender: string;
img: string;
isActive: boolean;
idGroup: string;
idPosition: string;
idUserRole: string;
};
export default function EditMember() {
const headerHeight = useHeaderHeight();
const dispatch = useDispatch()
const update = useSelector((state: any) => state.memberUpdate)
const { token, decryptToken } = useAuthSession()
const { id } = useLocalSearchParams<{ id: string }>();
const [errorImg, setErrorImg] = useState(false)
const [selectedImage, setSelectedImage] = useState<string | undefined | { uri: string }>(undefined);
const [choosePosition, setChoosePosition] = useState({ val: "", label: "" });
const [chooseRole, setChooseRole] = useState({ val: "", label: "" });
const [chooseGender, setChooseGender] = useState({ val: "", label: "" });
const [valSelect, setValSelect] = useState<"group" | "position" | "role" | "gender">("group");
const [isSelect, setSelect] = useState(false);
const [disableBtn, setDisableBtn] = useState(false)
const [valChoose, setValChoose] = useState("")
const [imgForm, setImgForm] = useState<any>();
const [loading, setLoading] = useState(false)
const [data, setData] = useState<Props>({
id: "",
name: "",
nik: "",
email: "",
phone: "",
gender: "",
img: "",
isActive: false,
idGroup: "",
idPosition: "",
idUserRole: "",
});
const [error, setError] = useState({
position: false,
nik: false,
name: false,
phone: false,
email: false,
gender: false,
role: false,
});
async function handleLoad() {
try {
const response = await apiGetProfile({ id: id });
setData(response.data);
setSelectedImage({ uri: `${ConstEnv.url_storage}/files/${response.data.img}`, });
setChoosePosition({
val: response.data.idPosition,
label: response.data.position,
});
setChooseRole({
val: response.data.idUserRole,
label: response.data.role,
});
setChooseGender({
val: response.data.gender,
label: response.data.gender == "M" ? "Laki-laki" : "Perempuan",
})
} catch (error) {
console.error(error);
}
}
useEffect(() => {
handleLoad();
}, []);
function validationForm(cat: string, val: any, label?: string) {
if (cat == "position") {
setChoosePosition({ val, label: String(label) });
setData({ ...data, idPosition: val });
if (val == "" || val == "null") {
setError({ ...error, position: true });
} else {
setError({ ...error, position: false });
}
} else if (cat == "role") {
setChooseRole({ val, label: String(label) });
setData({ ...data, idUserRole: val });
if (val == "" || val == "null") {
setError({ ...error, role: true });
} else {
setError({ ...error, role: false });
}
} else if (cat == "nik") {
setData({ ...data, nik: val });
if (val == "" || val.length !== 16) {
setError({ ...error, nik: true });
} else {
setError({ ...error, nik: false });
}
} else if (cat == "name") {
setData({ ...data, name: val });
if (!validateName(val)) {
setError({ ...error, name: true });
} else {
setError({ ...error, name: false });
}
} else if (cat == "email") {
setData({ ...data, email: val });
if (
val == "" ||
!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(val)
) {
setError({ ...error, email: true });
} else {
setError({ ...error, email: false });
}
} else if (cat == "phone") {
setData({ ...data, phone: val });
if (val == "" || !(val.length >= 9 && val.length <= 16)) {
setError({ ...error, phone: true });
} else {
setError({ ...error, phone: false });
}
} else if (cat == "gender") {
setChooseGender({ val, label: String(label) });
setData({ ...data, gender: val });
if (val == "" || val == "null") {
setError({ ...error, gender: true });
} else {
setError({ ...error, gender: false });
}
}
}
function checkForm() {
if (Object.values(error).some((v) => v == true) || Object.values(data).some((v) => v == "")) {
setDisableBtn(true)
} else {
setDisableBtn(false)
}
}
useEffect(() => {
checkForm()
}, [error, data])
async function handleEdit() {
try {
setLoading(true)
const hasil = await decryptToken(String(token?.current))
const fd = new FormData()
if (imgForm != undefined) {
fd.append("file", {
uri: imgForm.uri,
type: imgForm.mimeType || "image/jpeg",
name: imgForm.fileName || "image.jpg",
} as any);
} else {
fd.append("file", "undefined",);
}
fd.append("data", JSON.stringify(
{ user: hasil, ...data }
))
const response = await apiEditUser(fd, id)
if (response.success) {
Toast.show({ type: 'small', text1: 'Berhasil mengupdate data', })
dispatch(setUpdateMember(!update))
router.back()
} else {
Toast.show({ type: 'small', text1: response.message, })
}
} catch (error) {
console.error(error)
Toast.show({ type: 'small', text1: 'Terjadi kesalahan', })
} finally {
setLoading(false)
}
}
const pickImageAsync = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ["images"],
allowsEditing: true,
quality: 0.9,
aspect: [1, 1]
});
if (!result.canceled) {
setErrorImg(false)
setSelectedImage(result.assets[0].uri);
setImgForm(result.assets[0]);
} else {
setErrorImg(false)
}
};
return (
<SafeAreaView>
<Stack.Screen
options={{
// headerLeft: () => (
// <ButtonBackHeader
// onPress={() => {
// router.back();
// }}
// />
// ),
headerTitle: "Edit Anggota",
headerTitleAlign: "center",
// headerRight: () => (
// <ButtonSaveHeader
// disable={disableBtn || loading}
// category="update"
// onPress={() => {
// handleEdit()
// }}
// />
// ),
header: () => (
<AppHeader
title="Edit Anggota"
showBack={true}
onPressLeft={() => router.back()}
right={
<ButtonSaveHeader
disable={disableBtn || loading}
category="update"
onPress={() => {
handleEdit()
}}
/>
}
/>
)
}}
/>
<KeyboardAvoidingView
style={[Styles.h100]}
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
keyboardVerticalOffset={headerHeight}
>
<ScrollView showsVerticalScrollIndicator={false} style={[Styles.h100]}>
<View style={[Styles.p15]}>
<View style={{ justifyContent: "center", alignItems: "center" }}>
{
errorImg ?
<Pressable onPress={pickImageAsync}>
<Image
source={errorImg ? require("../../../../assets/images/user.jpg") : { uri: `${ConstEnv.url_storage}/files/${data?.img}` }}
style={[Styles.userProfileBig]}
onError={() => { setErrorImg(true) }}
/>
<View style={[Styles.absoluteIconPicker]}>
<MaterialCommunityIcons name="image" color={'white'} size={15} />
</View>
</Pressable>
:
selectedImage != undefined ? (
<Pressable onPress={pickImageAsync}>
<Image
src={
typeof selectedImage === "string"
? selectedImage
: selectedImage.uri
}
style={[Styles.userProfileBig]}
onError={() => { setErrorImg(true) }}
/>
<View style={[Styles.absoluteIconPicker]}>
<MaterialCommunityIcons name="image" color={'white'} size={15} />
</View>
</Pressable>
) : (
<Image
source={require("../../../../assets/images/user.jpg")}
style={[Styles.userProfileBig]}
/>
)
}
</View>
<SelectForm
label="Jabatan"
placeholder="Pilih Jabatan"
value={choosePosition.label}
required
onPress={() => {
setValChoose(choosePosition.val);
setValSelect("position");
setSelect(true);
}}
error={error.position}
errorText="Jabatan tidak boleh kosong"
/>
<SelectForm
label="User Role"
placeholder="Pilih Role"
value={chooseRole.label}
required
onPress={() => {
setValChoose(chooseRole.val);
setValSelect("role");
setSelect(true);
}}
error={error.role}
errorText="Role tidak boleh kosong"
/>
<InputForm
label="NIK"
type="numeric"
placeholder="NIK"
required
value={data?.nik}
error={error.nik}
errorText="NIK Harus 16 Karakter"
onChange={val => {
validationForm("nik", val)
}}
/>
<InputForm
label="Nama"
type="default"
placeholder="Nama"
required
value={data?.name}
error={error.name}
errorText="Nama harus 350 karakter (huruf, angka, spasi, dan simbol ringan (. , ' _ -))"
onChange={val => {
validationForm("name", val)
}}
/>
<InputForm
label="Email"
type="default"
placeholder="Email"
required
value={data?.email}
error={error.email}
errorText="Email tidak valid"
onChange={val => {
validationForm("email", val)
}}
/>
<InputForm
label="Nomor Telepon"
type="numeric"
placeholder="8XX-XXX-XXX"
required
itemLeft={<Text style={[Platform.OS === 'ios' && Styles.mt02]}>+62</Text>}
value={data?.phone}
error={error.phone}
errorText="Nomor Telepon tidak valid"
onChange={val => {
validationForm("phone", val)
}}
/>
<SelectForm
label="Jenis Kelamin"
placeholder="Pilih Jenis Kelamin"
value={chooseGender.label}
required
onPress={() => {
setValChoose(chooseGender.val);
setValSelect("gender");
setSelect(true);
}}
error={error.gender}
errorText="Jenis Kelamin tidak boleh kosong"
/>
</View>
</ScrollView>
</KeyboardAvoidingView>
<ModalSelect
category={valSelect}
close={setSelect}
onSelect={(value) => {
validationForm(valSelect, value.val, value.label);
}}
title={
valSelect == "group"
? "Lembaga Desa"
: valSelect == "position"
? "Jabatan"
: valSelect == "role"
? "User Role"
: "Jenis Kelamin"
}
open={isSelect}
idParent={valSelect == "position" ? data?.idGroup : ""}
valChoose={valChoose}
/>
</SafeAreaView>
);
}