141 lines
3.8 KiB
TypeScript
141 lines
3.8 KiB
TypeScript
|
|
import { useState } from "react";
|
||
|
|
import {
|
||
|
|
Dialog,
|
||
|
|
DialogContent,
|
||
|
|
DialogFooter,
|
||
|
|
DialogHeader,
|
||
|
|
DialogTitle,
|
||
|
|
DialogTrigger,
|
||
|
|
} from "@/components/ui/dialog";
|
||
|
|
import { Input } from "@/components/ui/input";
|
||
|
|
import { Button } from "@/components/ui/button";
|
||
|
|
import { Label } from "@/components/ui/label";
|
||
|
|
import { toast } from "sonner";
|
||
|
|
import { useForm, formOptions } from "@tanstack/react-form";
|
||
|
|
import axios from "axios";
|
||
|
|
|
||
|
|
interface AddBlacklistDialogProps {
|
||
|
|
onAdded?: () => void; // callback để refresh danh sách sau khi thêm
|
||
|
|
}
|
||
|
|
|
||
|
|
const formOpts = formOptions({
|
||
|
|
defaultValues: { appName: "", processName: "" },
|
||
|
|
});
|
||
|
|
|
||
|
|
export function AddBlacklistDialog({ onAdded }: AddBlacklistDialogProps) {
|
||
|
|
const [isOpen, setIsOpen] = useState(false);
|
||
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||
|
|
const [isDone, setIsDone] = useState(false);
|
||
|
|
|
||
|
|
const form = useForm({
|
||
|
|
...formOpts,
|
||
|
|
onSubmit: async ({ value }) => {
|
||
|
|
if (!value.appName || !value.processName) {
|
||
|
|
toast.error("Vui lòng nhập đầy đủ tên ứng dụng và tiến trình");
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
setIsSubmitting(true);
|
||
|
|
|
||
|
|
await axios.post("/api/appversions/add-blacklist", {
|
||
|
|
appName: value.appName,
|
||
|
|
processName: value.processName,
|
||
|
|
});
|
||
|
|
|
||
|
|
toast.success("Đã thêm vào blacklist!");
|
||
|
|
setIsDone(true);
|
||
|
|
|
||
|
|
if (onAdded) onAdded();
|
||
|
|
} catch (error) {
|
||
|
|
console.error(error);
|
||
|
|
toast.error("Không thể thêm vào blacklist");
|
||
|
|
} finally {
|
||
|
|
setIsSubmitting(false);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
const handleDialogClose = (open: boolean) => {
|
||
|
|
if (isSubmitting) return;
|
||
|
|
setIsOpen(open);
|
||
|
|
if (!open) {
|
||
|
|
setIsDone(false);
|
||
|
|
form.reset();
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<Dialog open={isOpen} onOpenChange={handleDialogClose}>
|
||
|
|
<DialogTrigger asChild>
|
||
|
|
<Button>Thêm vào Blacklist</Button>
|
||
|
|
</DialogTrigger>
|
||
|
|
|
||
|
|
<DialogContent>
|
||
|
|
<DialogHeader>
|
||
|
|
<DialogTitle>Thêm ứng dụng vào danh sách cấm</DialogTitle>
|
||
|
|
</DialogHeader>
|
||
|
|
|
||
|
|
<form
|
||
|
|
className="space-y-4"
|
||
|
|
onSubmit={(e) => {
|
||
|
|
e.preventDefault();
|
||
|
|
e.stopPropagation();
|
||
|
|
form.handleSubmit();
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<form.Field name="appName">
|
||
|
|
{(field) => (
|
||
|
|
<div>
|
||
|
|
<Label>Tên ứng dụng</Label>
|
||
|
|
<Input
|
||
|
|
value={field.state.value}
|
||
|
|
onChange={(e) => field.handleChange(e.target.value)}
|
||
|
|
placeholder="Ví dụ: Google Chrome"
|
||
|
|
disabled={isSubmitting || isDone}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</form.Field>
|
||
|
|
|
||
|
|
<form.Field name="processName">
|
||
|
|
{(field) => (
|
||
|
|
<div>
|
||
|
|
<Label>Tên tiến trình</Label>
|
||
|
|
<Input
|
||
|
|
value={field.state.value}
|
||
|
|
onChange={(e) => field.handleChange(e.target.value)}
|
||
|
|
placeholder="chrome.exe"
|
||
|
|
disabled={isSubmitting || isDone}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</form.Field>
|
||
|
|
|
||
|
|
<DialogFooter>
|
||
|
|
{!isDone ? (
|
||
|
|
<>
|
||
|
|
<Button
|
||
|
|
type="button"
|
||
|
|
variant="outline"
|
||
|
|
onClick={() => handleDialogClose(false)}
|
||
|
|
disabled={isSubmitting}
|
||
|
|
>
|
||
|
|
Hủy
|
||
|
|
</Button>
|
||
|
|
<Button type="submit" disabled={isSubmitting}>
|
||
|
|
{isSubmitting ? "Đang thêm..." : "Thêm"}
|
||
|
|
</Button>
|
||
|
|
</>
|
||
|
|
) : (
|
||
|
|
<Button type="button" onClick={() => handleDialogClose(false)}>
|
||
|
|
Hoàn tất
|
||
|
|
</Button>
|
||
|
|
)}
|
||
|
|
</DialogFooter>
|
||
|
|
</form>
|
||
|
|
</DialogContent>
|
||
|
|
</Dialog>
|
||
|
|
);
|
||
|
|
}
|