Implement LoadFilePage page
This commit is contained in:
106
web/src/pages/LoadFilePage/LoadFileForm.tsx
Normal file
106
web/src/pages/LoadFilePage/LoadFileForm.tsx
Normal file
@@ -0,0 +1,106 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
|
||||
export type LoadFileFormProps = {
|
||||
profiles: string[];
|
||||
servers: string[];
|
||||
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 }: 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 handleSubmit = useCallback(async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!selectedFile || !formData.profile || !formData.server) {
|
||||
return;
|
||||
}
|
||||
|
||||
onSubmit?.(selectedFile, formData.profile, formData.server);
|
||||
}, [formData, formData, selectedFile, onSubmit]);
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="field">
|
||||
<label className="label">CSV File</label>
|
||||
<div className="control">
|
||||
<div className={`file is-fullwidth ${!!selectedFile ? "has-name" : ""}`}>
|
||||
<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="button is-link is-fullwidth"
|
||||
>
|
||||
Load transactions
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user