import React, { useEffect, useState } from "react"; import { Box, Label, Flex, Button, Text, Checkbox, Divider } from "theme-ui"; import SimpleBar from "simplebar-react"; import Modal from "../components/Modal"; import LoadingOverlay from "../components/LoadingOverlay"; import { getDatabase } from "../database"; function SelectDataModal({ isOpen, onRequestClose, onConfirm, confirmText, label, databaseName, filter, }) { const [maps, setMaps] = useState({}); const [tokensByMap, setTokensByMap] = useState({}); const [tokens, setTokens] = useState({}); const [isLoading, setIsLoading] = useState(false); const hasMaps = Object.values(maps).length > 0; const hasTokens = Object.values(tokens).length > 0; useEffect(() => { async function loadData() { if (isOpen && databaseName) { setIsLoading(true); const db = getDatabase({}, databaseName); let loadedMaps = {}; let loadedTokensByMap = {}; let loadedTokens = {}; await db .table("maps") .filter((map) => filter("maps", map, map.id)) .each((map) => { loadedMaps[map.id] = { name: map.name, id: map.id, checked: true }; }); await db .table("states") .filter((state) => filter("states", state, state.mapId)) .each((state) => { loadedTokensByMap[state.mapId] = new Set( Object.values(state.tokens).map( (tokenState) => tokenState.tokenId ) ); }); await db .table("tokens") .filter((token) => filter("tokens", token, token.id)) .each((token) => { loadedTokens[token.id] = { name: token.name, id: token.id, checked: true, }; }); db.close(); setMaps(loadedMaps); setTokensByMap(loadedTokensByMap); setTokens(loadedTokens); setIsLoading(false); } else { setMaps({}); setTokens({}); } } loadData(); }, [isOpen, databaseName, filter]); // An object mapping a tokenId to how many checked maps it is currently used in const [tokenUsedCount, setTokenUsedCount] = useState({}); useEffect(() => { let tokensUsed = {}; for (let mapId in maps) { if (maps[mapId].checked && mapId in tokensByMap) { for (let tokenId of tokensByMap[mapId]) { if (tokenId in tokensUsed) { tokensUsed[tokenId] += 1; } else { tokensUsed[tokenId] = 1; } } } } setTokenUsedCount(tokensUsed); // Update tokens to ensure used tokens are checked setTokens((prevTokens) => { let newTokens = { ...prevTokens }; for (let id in newTokens) { if (id in tokensUsed) { newTokens[id].checked = true; } } return newTokens; }); }, [maps, tokensByMap]); function handleConfirm() { let checkedMaps = Object.values(maps).filter((map) => map.checked); let checkedTokens = Object.values(tokens).filter((token) => token.checked); onConfirm(checkedMaps, checkedTokens); } return ( {!hasMaps && !hasTokens && ( No custom maps or tokens found. )} {hasMaps && ( <> {Object.values(maps).map((map) => ( ))} )} {hasMaps && hasTokens && } {hasTokens && ( <> {Object.values(tokens).map((token) => ( {token.id in tokenUsedCount && ( Token used in {tokenUsedCount[token.id]} selected map {tokenUsedCount[token.id] > 1 && "s"} )} ))} )} {isLoading && } ); } SelectDataModal.defaultProps = { label: "Select data", confirmText: "Yes", filter: () => true, databaseName: "OwlbearRodeoDB", }; export default SelectDataModal;