import React, { useState, useCallback, MouseEvent, ChangeEvent } from 'react'; import type { FeatureCollection } from 'geojson'; import invariant from 'tiny-invariant'; import { readGeoFile } from '../readGeoFile'; import { generateId } from '../../shared/maplibre/utils'; import { CreateFeatures, DeleteFeatures } from '../hooks'; export function ImportFileInput({ featureCollection, createFeatures, deleteFeatures }: { featureCollection: FeatureCollection; createFeatures: CreateFeatures; deleteFeatures: DeleteFeatures; }) { const { inputs, addInputFile, removeInputFile, onFileChange } = useImportFiles(featureCollection, { createFeatures, deleteFeatures }); return (
{inputs.map((input) => (
onFileChange(e, input.id)} /> {input.hasValue && ( removeInputFile(e, input.id)} > )}
))}
); } type FileInput = { id: string; disabled: boolean; hasValue: boolean; filename: string; }; function useImportFiles( featureCollection: FeatureCollection, { createFeatures, deleteFeatures }: { createFeatures: CreateFeatures; deleteFeatures: DeleteFeatures } ) { const [inputs, setInputs] = useState([]); const addInput = useCallback( (input: FileInput) => { setInputs((inputs) => [...inputs, input]); }, [setInputs] ); const removeInput = useCallback( (inputId: string) => { setInputs((inputs) => inputs.filter((input) => input.id !== inputId)); }, [setInputs] ); const onFileChange = useCallback( async (event: ChangeEvent, inputId: string) => { invariant(event.target.files, ''); const { features, filename } = await readGeoFile(event.target.files[0]); createFeatures({ features, external: true }); setInputs((inputs) => { return inputs.map((input) => { if (input.id === inputId) { return { ...input, disabled: true, hasValue: true, filename }; } return input; }); }); }, [setInputs, createFeatures] ); const addInputFile = useCallback( (event: MouseEvent) => { event.preventDefault(); addInput({ id: generateId(), disabled: false, hasValue: false, filename: '' }); }, [addInput] ); const removeInputFile = useCallback( (event: MouseEvent, inputId: string) => { event.preventDefault(); const filename = inputs.find((input) => input.id === inputId)?.filename; const features = featureCollection.features.filter( (feature) => feature.properties?.filename == filename ); deleteFeatures({ features, external: true }); removeInput(inputId); }, [inputs, removeInput, deleteFeatures, featureCollection] ); return { inputs, onFileChange, addInputFile, removeInputFile }; }