import { ButtonForm } from "@/components/buttonForm" import DrawerBottom from "@/components/drawerBottom" import ImageUser from "@/components/imageNew" import ImageWithLabel from "@/components/imageWithLabel" import InputSearch from "@/components/inputSearch" import Text from "@/components/Text" import { ConstEnv } from "@/constants/ConstEnv" import Styles from "@/constants/Styles" import { apiGetDivision, apiGetDivisionMember, apiGetUser } from "@/lib/api" import { setMemberChoose } from "@/lib/memberChoose" import { useAuthSession } from "@/providers/AuthProvider" import { useTheme } from "@/providers/ThemeProvider" import { AntDesign, Ionicons } from "@expo/vector-icons" import { useEffect, useState } from "react" import { ActivityIndicator, Pressable, ScrollView, View } from "react-native" import { useDispatch, useSelector } from "react-redux" type Member = { idUser: string; name: string; img: string } type DivisionItem = { id: string name: string expanded: boolean membersLoaded: boolean members: Member[] } type Props = { open: boolean close: (value: boolean) => void idGroup: string } export default function ModalSelectMemberByDivision({ open, close, idGroup }: Props) { const { token, decryptToken } = useAuthSession() const { colors } = useTheme() const dispatch = useDispatch() const entitiesMember = useSelector((state: any) => state.memberChoose) const [divisions, setDivisions] = useState([]) const [selectMember, setSelectMember] = useState([]) const [search, setSearch] = useState('') const [loadingDivisions, setLoadingDivisions] = useState(false) const [loadingIds, setLoadingIds] = useState([]) const [searchResults, setSearchResults] = useState([]) const [loadingSearch, setLoadingSearch] = useState(false) async function loadDivisions() { if (!idGroup) return setLoadingDivisions(true) try { const hasil = await decryptToken(String(token?.current)) const response = await apiGetDivision({ user: hasil, search: '', group: idGroup, active: 'true', kategori: 'semua', page: 1 }) const divisionList: DivisionItem[] = (response.data ?? []).map((d: any) => ({ id: d.id, name: d.name, expanded: false, membersLoaded: false, members: [] })) const withMembers = await Promise.all( divisionList.map(async (d) => { try { const res = await apiGetDivisionMember({ user: hasil, id: d.id, search: '' }) const members: Member[] = (res.data ?? []).map((m: any) => ({ idUser: m.idUser, name: m.name, img: m.img })) return { ...d, members, membersLoaded: true } } catch { return { ...d, membersLoaded: true } } }) ) setDivisions(withMembers) } catch { setDivisions([]) } finally { setLoadingDivisions(false) } } async function fetchMembers(divisionId: string): Promise { setLoadingIds(prev => [...prev, divisionId]) try { const hasil = await decryptToken(String(token?.current)) const response = await apiGetDivisionMember({ user: hasil, id: divisionId, search: '' }) const members: Member[] = (response.data ?? []).map((m: any) => ({ idUser: m.idUser, name: m.name, img: m.img })) setDivisions(prev => prev.map(d => d.id === divisionId ? { ...d, members, membersLoaded: true } : d )) return members } catch { return [] } finally { setLoadingIds(prev => prev.filter(id => id !== divisionId)) } } async function searchUsers(query: string) { setLoadingSearch(true) try { const hasil = await decryptToken(String(token?.current)) const response = await apiGetUser({ user: hasil, active: 'true', search: query, group: idGroup }) setSearchResults((response.data ?? []).filter((i: any) => i.idUserRole !== 'supadmin')) } catch { setSearchResults([]) } finally { setLoadingSearch(false) } } useEffect(() => { if (open) { loadDivisions(); setSelectMember(entitiesMember) } }, [open]) useEffect(() => { if (!open) return if (search) { searchUsers(search) } else { setSearchResults([]) loadDivisions() } }, [search]) async function handleTapDivision(division: DivisionItem) { let members = division.members if (!division.membersLoaded) members = await fetchMembers(division.id) setDivisions(prev => prev.map(d => d.id === division.id ? { ...d, expanded: true, members, membersLoaded: true } : d )) const allSelected = members.length > 0 && members.every(m => selectMember.some(s => s.idUser === m.idUser) ) if (allSelected) { setSelectMember(prev => prev.filter(s => !members.some(m => m.idUser === s.idUser))) } else { const existingIds = new Set(selectMember.map(s => s.idUser)) setSelectMember(prev => [...prev, ...members.filter(m => !existingIds.has(m.idUser))]) } } async function handleToggleExpand(divisionId: string) { const division = divisions.find(d => d.id === divisionId)! if (!division.membersLoaded && !division.expanded) await fetchMembers(divisionId) setDivisions(prev => prev.map(d => d.id === divisionId ? { ...d, expanded: !d.expanded } : d )) } function handleToggleMember(member: Member) { if (selectMember.some(s => s.idUser === member.idUser)) { setSelectMember(prev => prev.filter(s => s.idUser !== member.idUser)) } else { setSelectMember(prev => [...prev, member]) } } function handleConfirm() { dispatch(setMemberChoose(selectMember)) handleClose() } function handleClose() { setDivisions([]) setSelectMember([]) setSearch('') close(false) } return ( {selectMember.length > 0 ? ( {selectMember.map((item, index) => ( handleToggleMember(item)} /> ))} ) : ( Tidak ada member yang dipilih ) } {search ? ( loadingSearch ? ( ) : searchResults.length > 0 ? ( searchResults.map((item, idx) => ( handleToggleMember({ idUser: item.id, name: item.name, img: item.img })} > {item.name} {selectMember.some(s => s.idUser === item.id) && ( )} )) ) : ( Tidak ada hasil ) ) : loadingDivisions ? ( ) : divisions.length > 0 ? ( divisions.map((division) => { const selectedCount = division.members.filter(m => selectMember.some(s => s.idUser === m.idUser) ).length const allSelected = division.membersLoaded && division.members.length > 0 && selectedCount === division.members.length const someSelected = selectedCount > 0 && !allSelected const isLoadingThis = loadingIds.includes(division.id) return ( handleTapDivision(division)} > {division.name} {division.membersLoaded && ( {selectedCount > 0 ? `${selectedCount} dari ${division.members.length} dipilih` : `${division.members.length} anggota`} )} {isLoadingThis ? ( ) : allSelected ? ( ) : someSelected ? ( ) : null} handleToggleExpand(division.id)} style={{ paddingLeft: 10 }} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }} > {division.expanded && division.members.map((member, idx) => ( handleToggleMember(member)} > {member.name} {selectMember.some(s => s.idUser === member.idUser) && ( )} ))} ) }) ) : ( Tidak ada divisi )} ) }