Files
actual-importer/web/src/pages/LoadFilePage/LoadFileForm.tsx

109 lines
3.4 KiB
TypeScript

import classNames from "classnames";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
export type LoadFileFormProps = {
profiles: string[];
servers: string[];
loading: boolean;
defaultProfile?: string;
defaultServer?: string;
onSubmit?: (csvFile: File, profile: string, server: string) => Promise<void>;
}
type Form = {
files?: FileList;
profile?: string;
server?: string;
};
export default function LoadFileForm({ profiles, servers, defaultProfile, defaultServer, onSubmit, loading }: LoadFileFormProps) {
const fileInput = useRef<HTMLInputElement>(null);
const [formData, setFormData] = useState<Form>({});
useEffect(() => {
setFormData({
...formData,
profile: defaultProfile,
server: defaultServer
});
}, [setFormData, defaultProfile, defaultServer]);
const selectedFile = useMemo(() => {
if ((formData.files?.length ?? 0) > 0) {
return formData.files?.[0];
}
return undefined;
}, [formData.files]);
const isValid = useMemo(() => selectedFile && formData.profile && formData.server, [formData, selectedFile]);
const handleSubmit = useCallback(async (e: React.FormEvent) => {
e.preventDefault();
if (!selectedFile || !formData.profile || !formData.server) {
return;
}
onSubmit?.(selectedFile, formData.profile, formData.server);
}, [formData, selectedFile, onSubmit]);
return (
<form onSubmit={handleSubmit}>
<div className="field">
<label className="label">CSV File</label>
<div className="control">
<div className={classNames("file", "is-fullwidth", { "has-name": selectedFile })}>
<label className="file-label">
<input className="file-input" ref={fileInput} type="file" accept=".csv" onChange={(e) => setFormData({...formData, files: e.target.files ?? undefined})} required />
<span className="file-cta">
<span className="file-label">Choose a file</span>
</span>
{!!selectedFile && (<span className="file-name">{selectedFile.name}</span>)}
</label>
</div>
</div>
</div>
<div className="field">
<label className="label">Profile</label>
<div className="control">
<div className="select is-fullwidth">
<select
value={formData.profile}
onChange={e => setFormData({ ...formData, profile: e.target.value })}
>
{profiles.map(p => <option value={p} key={p}>{p}</option>)}
</select>
</div>
</div>
</div>
<div className="field">
<label className="label">Server</label>
<div className="control">
<div className="select is-fullwidth">
<select
value={formData.server}
onChange={e => setFormData({ ...formData, server: e.target.value })}
>
{servers.map(p => <option value={p} key={p}>{p}</option>)}
</select>
</div>
</div>
</div>
<div className="field mt-5">
<div className="control">
<button
type="submit"
className={classNames("button", "is-link", "is-fullwidth", { 'is-loading': loading })}
disabled={!isValid || loading}>Load transactions
</button>
</div>
</div>
</form>
);
}