TTMT.ManageWebGUI/src/components/forms/upload-file-form.tsx

120 lines
3.5 KiB
TypeScript
Raw Normal View History

2025-11-19 14:55:14 +07:00
import { useForm } from "@tanstack/react-form";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
import type { AxiosProgressEvent } from "axios";
import { useState } from "react";
import { toast } from "sonner";
interface UploadVersionFormProps {
onSubmit: (fd: FormData, config?: { onUploadProgress: (e: AxiosProgressEvent) => void }) => Promise<void>;
closeDialog: () => void;
}
export function UploadVersionForm({ onSubmit, closeDialog }: UploadVersionFormProps) {
const [uploadPercent, setUploadPercent] = useState(0);
const [isUploading, setIsUploading] = useState(false);
const [isDone, setIsDone] = useState(false);
const form = useForm({
defaultValues: { files: new DataTransfer().files, newVersion: "" },
onSubmit: async ({ value }) => {
if (!value.newVersion || value.files.length === 0) {
toast.error("Vui lòng điền đầy đủ thông tin");
return;
}
try {
setIsUploading(true);
setUploadPercent(0);
setIsDone(false);
const fd = new FormData();
Array.from(value.files).forEach((f) => fd.append("FileInput", f));
fd.append("Version", value.newVersion);
await onSubmit(fd, {
onUploadProgress: (e: AxiosProgressEvent) => {
if (e.total) {
const progress = Math.round((e.loaded * 100) / e.total);
setUploadPercent(progress);
}
},
});
setIsDone(true);
} catch (error) {
console.error("Upload error:", error);
toast.error("Upload thất bại!");
} finally {
setIsUploading(false);
}
},
});
return (
<form
className="space-y-4"
onSubmit={(e) => {
e.preventDefault();
form.handleSubmit();
}}
>
<form.Field name="newVersion">
{(field) => (
<div>
<Label>Phiên bản</Label>
<Input
value={field.state.value}
onChange={(e) => field.handleChange(e.target.value)}
placeholder="1.0.0"
disabled={isUploading || isDone}
/>
</div>
)}
</form.Field>
<form.Field name="files">
{(field) => (
<div>
<Label>File</Label>
<Input
type="file"
onChange={(e) => e.target.files && field.handleChange(e.target.files)}
disabled={isUploading || isDone}
/>
</div>
)}
</form.Field>
{(uploadPercent > 0 || isUploading || isDone) && (
<div className="space-y-2">
<div className="flex justify-between text-sm">
<span>{isDone ? "Hoàn tất!" : "Đang tải lên..."}</span>
<span>{uploadPercent}%</span>
</div>
<Progress value={uploadPercent} className="w-full" />
</div>
)}
<div className="flex justify-end gap-2">
{!isDone ? (
<>
<Button type="button" variant="outline" onClick={closeDialog} disabled={isUploading}>
Hủy
</Button>
<Button type="submit" disabled={isUploading}>
{isUploading ? "Đang tải..." : "Upload"}
</Button>
</>
) : (
<Button type="button" onClick={closeDialog}>
Hoàn tất
</Button>
)}
</div>
</form>
);
}