import BorderBottomItem from "@/components/borderBottomItem"; import { ButtonForm } from "@/components/buttonForm"; import ButtonTab from "@/components/buttonTab"; import DrawerBottom from "@/components/drawerBottom"; import { InputForm } from "@/components/inputForm"; import InputSearch from "@/components/inputSearch"; import LabelStatus from "@/components/labelStatus"; import MenuItemRow from "@/components/menuItemRow"; import ModalConfirmation from "@/components/ModalConfirmation"; import SkeletonTwoItem from "@/components/skeletonTwoItem"; import Text from "@/components/Text"; import WrapTab from "@/components/wrapTab"; import Styles from "@/constants/Styles"; import { apiDeletePosition, apiEditPosition, apiGetPosition } from "@/lib/api"; import { setUpdatePosition } from "@/lib/positionSlice"; import { useAuthSession } from "@/providers/AuthProvider"; import { useTheme } from "@/providers/ThemeProvider"; import { AntDesign, Feather, MaterialCommunityIcons } from "@expo/vector-icons"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useLocalSearchParams } from "expo-router"; import { useEffect, useMemo, useState } from "react"; import { RefreshControl, View, VirtualizedList } from "react-native"; import Toast from "react-native-toast-message"; import { useDispatch, useSelector } from "react-redux"; type Props = { name: string; idGroup: string; group: string; id: string; isActive: boolean } export default function Index() { const { token, decryptToken } = useAuthSession() const { colors } = useTheme() const { active, group } = useLocalSearchParams<{ active?: string, group?: string }>() const [status, setStatus] = useState<'true' | 'false'>(active == 'false' ? 'false' : 'true') const entityUser = useSelector((state: any) => state.user) const [isModal, setModal] = useState(false) const [isVisibleEdit, setVisibleEdit] = useState(false) const [search, setSearch] = useState('') const [loadingSubmit, setLoadingSubmit] = useState(false) const [chooseData, setChooseData] = useState({ name: '', id: '', active: false, idGroup: '' }) const [error, setError] = useState({ name: false, }); const queryClient = useQueryClient() const [refreshing, setRefreshing] = useState(false) const [showDeleteModal, setShowDeleteModal] = useState(false) const dispatch = useDispatch() const update = useSelector((state: any) => state.positionUpdate) // TanStack Query for Positions const { data: queryData, isLoading, refetch } = useQuery({ queryKey: ['positions', { status, search, group }], queryFn: async () => { const hasil = await decryptToken(String(token?.current)) const response = await apiGetPosition({ user: hasil, active: status, search: search, group: String(group) }) return response; }, enabled: !!token?.current, staleTime: 0, }) const data = useMemo(() => queryData?.data || [], [queryData]) const nameGroup = useMemo(() => queryData?.filter?.name || "", [queryData]) useEffect(() => { refetch() }, [update, refetch]) function handleChooseData(id: string, name: string, active: boolean, group: string) { setChooseData({ id, name, active, idGroup: group }) setModal(true) } async function handleDelete() { try { const hasil = await decryptToken(String(token?.current)) const response = await apiDeletePosition({ user: hasil, isActive: chooseData.active }, chooseData.id) dispatch(setUpdatePosition(!update)) } catch (error: any) { console.error(error); const message = error?.response?.data?.message || "Gagal menghapus data" Toast.show({ type: 'small', text1: message }) } finally { setModal(false) Toast.show({ type: 'small', text1: 'Berhasil mengupdate data', }) } } 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) if (response.success) { dispatch(setUpdatePosition(!update)) } else { Toast.show({ type: 'small', text1: response.message, }) } } catch (error: any) { console.error(error); const message = error?.response?.data?.message || "Gagal mengubah data" Toast.show({ type: 'small', text1: message }) } finally { setLoadingSubmit(false) setVisibleEdit(false) setModal(false) } } function validationForm(value: string) { setChooseData({ ...chooseData, name: value }) if (value == "") { setError({ ...error, name: true }) } else { setError({ ...error, name: false }) } } function checkForm() { if (Object.values(error).some((v) => v == true)) return false handleEdit() } const arrSkeleton = [0, 1, 2, 3, 4] const handleRefresh = async () => { setRefreshing(true) await queryClient.invalidateQueries({ queryKey: ['positions'] }) setRefreshing(false) }; const getItem = (_data: unknown, index: number): Props => ({ id: data[index].id, name: data[index].name, idGroup: data[index].idGroup, group: data[index].group, isActive: data[index].isActive, }); return ( { setStatus("true") }} label="Aktif" icon={} n={2} /> { setStatus("false") }} label="Tidak Aktif" icon={} n={2} /> { (entityUser.role == "supadmin" || entityUser.role == "developer") && Filter : } { isLoading ? arrSkeleton.map((item, index) => { return ( ) }) : data.length > 0 ? data.length} getItem={getItem} renderItem={({ item, index }: { item: Props, index: number }) => { return ( { entityUser.role != "user" && handleChooseData(item.id, item.name, item.isActive, item.idGroup) }} borderType="all" icon={ } title={item.name} subtitle={item.group} /> ) }} keyExtractor={(item, index) => String(index)} showsVerticalScrollIndicator={false} refreshControl={ } /> : Tidak ada data } setModal(false)} title={chooseData.name}> } title={chooseData.active ? 'Non Aktifkan' : "Aktifkan"} onPress={() => { setModal(false) setTimeout(() => { setShowDeleteModal(true) }, 600) }} /> } title="Edit" onPress={() => { setModal(false) setTimeout(() => { setVisibleEdit(true) }, 600) }} /> setVisibleEdit(false)} title="Edit Jabatan"> { validationForm(val) }} error={error.name} errorText="Nama jabatan tidak boleh kosong" /> { handleEdit() }} disabled={Object.values(error).some((v) => v == true) || chooseData.name == "" || loadingSubmit} /> { setShowDeleteModal(false) handleDelete() }} onCancel={() => setShowDeleteModal(false)} confirmText={chooseData.active ? "Nonaktifkan" : "Aktifkan"} cancelText="Batal" /> ) }