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
};
}