Files
mobile-darmasaba/components/modalSelectMultiple.tsx
amaliadwiy 42bf1589b4 upd: tampilan
Deskripsi:
- masang toast
- ganti tag Text

No Issues
2025-07-29 11:41:03 +08:00

208 lines
7.7 KiB
TypeScript

import Styles from "@/constants/Styles"
import { apiGetDivisionGroup, apiGetDocumentInformasi, apiGetListDivisionByIdDivision } from "@/lib/api"
import { useAuthSession } from "@/providers/AuthProvider"
import { AntDesign } from "@expo/vector-icons"
import { useEffect, useState } from "react"
import { Pressable, ScrollView, View } from "react-native"
import Toast from "react-native-toast-message"
import Text from "./Text"
import { ButtonForm } from "./buttonForm"
import DrawerBottom from "./drawerBottom"
type Props = {
open: boolean
close: (value: boolean) => void
title: string
category: 'share-division' | 'choose-division'
choose: string
onSelect: (value: any[]) => void
value?: any
item?: any
}
type CheckedState = {
[key: string]: string[];
}
type GroupData = {
id: string;
name: string;
Division: {
id: string;
name: string;
}[];
}
export default function ModalSelectMultiple({ open, close, title, category, choose, onSelect, value, item }: Props) {
const [isChoose, setChoose] = useState(choose)
const { token, decryptToken } = useAuthSession()
const [data, setData] = useState<any>([])
const [checked, setChecked] = useState<CheckedState>({});
const [selectedDivision, setSelectedDivision] = useState<any>([]);
async function handleLoadChooseDivision() {
try {
const hasil = await decryptToken(String(token?.current))
const response = await apiGetDivisionGroup({ user: hasil })
setData(response.data)
if (value?.length > 0) {
const formatArray = value.reduce((result: any, obj: any) => {
result[obj.id] = obj.Division.map((item: any) => item.id);
return result;
}, {})
setChecked(formatArray)
}
} catch (error) {
console.error(error)
}
}
async function handleLoadShareDivision() {
try {
const hasil = await decryptToken(String(token?.current))
const response = await apiGetListDivisionByIdDivision({ user: hasil, search: '', division: value })
const response2 = await apiGetDocumentInformasi({ user: hasil, item: item, cat: 'share' })
setData(response.data.filter((i: any) => i.id != value))
setSelectedDivision(response2.data)
} catch (error) {
console.error(error)
}
}
useEffect(() => {
if (open) {
if (category == 'choose-division') {
handleLoadChooseDivision()
} else if (category == 'share-division') {
handleLoadShareDivision()
}
}
}, [open]);
const handleCheck = (groupId: string, divisionId: string) => {
const newChecked = { ...checked };
if (newChecked[groupId]) {
if (newChecked[groupId].includes(divisionId)) {
newChecked[groupId] = newChecked[groupId].filter(item => item !== divisionId);
if (newChecked[groupId]?.length === 0) {
delete newChecked[groupId];
}
} else {
newChecked[groupId].push(divisionId);
}
} else {
newChecked[groupId] = [divisionId];
}
setChecked(newChecked);
};
const handleGroupCheck = (groupId: string) => {
const newChecked = { ...checked };
if (newChecked[groupId]) {
delete newChecked[groupId];
} else {
if (data.find((item: { id: string }) => item.id === groupId)?.Division?.length == 0) {
return Toast.show({ type: 'small', text1: 'Tidak ada divisi', })
}
newChecked[groupId] = data.find((item: { id: string }) => item.id === groupId)?.Division.map((item: { id: any }) => item.id) || [];
}
setChecked(newChecked);
};
const handleDivisionClick = (index: number) => {
if (selectedDivision.some((i: any) => i.id == data[index].id)) {
setSelectedDivision(
selectedDivision.filter((i: any) => i.id != data[index].id)
);
} else {
setSelectedDivision([
...selectedDivision,
{ id: data[index].id, name: data[index].name },
]);
}
};
const handleSubmit = () => {
if (category == "choose-division") {
const selectedGroups: GroupData[] = [];
Object.keys(checked).forEach((groupId) => {
const group = data.find((item: { id: string }) => item.id === groupId);
if (group) {
selectedGroups.push({
id: group.id,
name: group.name,
Division: group.Division.filter((division: { id: string }) => checked[groupId].includes(division.id)),
});
}
});
onSelect(selectedGroups);
} else {
onSelect(selectedDivision);
}
};
return (
<DrawerBottom animation="slide" isVisible={open} setVisible={close} title={title} height={85}>
<ScrollView style={[Styles.mb50]}>
{
category == 'share-division' ?
<>
{
data.map((item: any, index: number) => {
return (
<Pressable key={index} style={[Styles.itemSelectModal]} onPress={() => {
handleDivisionClick(index)
}}>
<Text numberOfLines={1} style={[Styles.w80]}>{item.name}</Text>
{
selectedDivision.some((i: any) => i.id == item.id)
? <AntDesign name="check" size={18} />
: <></>
}
</Pressable>
)
})
}
</>
:
data.map((item: any, index: number) => {
return (
<View key={index}>
<Pressable style={[Styles.itemSelectModal]} onPress={() => { handleGroupCheck(item.id) }}>
<Text style={[Styles.textMediumSemiBold]}>{item.name}</Text>
{
checked[item.id] && checked[item.id]?.length === item.Division?.length
? <AntDesign name="check" size={20} />
: (checked[item.id] && checked[item.id]?.length > 0 && checked[item.id]?.length < item.Division?.length)
? <AntDesign name="minus" size={20} />
: <></>
}
</Pressable>
{
item.Division.map((child: any, v: number) => {
return (
<Pressable key={v} style={[Styles.itemSelectModal]} onPress={() => { handleCheck(item.id, child.id) }}>
<Text style={[Styles.ml10, Styles.textMediumNormal, Styles.w80]} numberOfLines={1} ellipsizeMode="tail" >{child.name}</Text>
{
checked[item.id] && checked[item.id].includes(child.id) && <AntDesign name="check" size={20} />
}
</Pressable>
)
})
}
</View>
)
})
}
</ScrollView>
<View style={[Styles.absolute0, { width: '100%' }]}>
<ButtonForm text="PILIH" onPress={() => { handleSubmit() }} />
</View>
</DrawerBottom>
)
}