feat(topic state and command) - add & delete topic
This commit is contained in:
@@ -1,10 +1,57 @@
|
||||
import { useState } from "react";
|
||||
import { useTopics } from "../hooks/queries";
|
||||
import { Edit, Trash2 } from "lucide-react";
|
||||
import { useDeleteTopic } from "../hooks/mutations";
|
||||
|
||||
type PendingDelete = {
|
||||
open: boolean;
|
||||
topic: string;
|
||||
};
|
||||
|
||||
export default function StateSection() {
|
||||
const { data } = useTopics();
|
||||
const { data, isLoading } = useTopics();
|
||||
const deleteTopic = useDeleteTopic();
|
||||
const [pending, setPending] = useState<PendingDelete>({
|
||||
open: false,
|
||||
topic: "",
|
||||
});
|
||||
|
||||
const handleDelete = (topic: string) => {
|
||||
if (deleteTopic.isPending) return;
|
||||
setPending({ open: true, topic });
|
||||
};
|
||||
|
||||
const handleConfirmDelete = () => {
|
||||
if (!pending.topic || deleteTopic.isPending) return;
|
||||
deleteTopic.mutate(
|
||||
{ topic: pending.topic, type: "state-reply" },
|
||||
{
|
||||
onSuccess: () => setPending({ open: false, topic: "" }),
|
||||
onError: () => setPending({ open: false, topic: "" }),
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
if (deleteTopic.isPending) return;
|
||||
setPending({ open: false, topic: "" });
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{isLoading &&
|
||||
Array.from({ length: 3 }).map((_, index) => (
|
||||
<div
|
||||
key={`loading-${index}`}
|
||||
className="bg-white border-b border-neutral-200 p-4 flex items-center justify-between"
|
||||
>
|
||||
<div className="h-4 w-40 animate-pulse rounded bg-neutral-200" />
|
||||
<div className="flex gap-2">
|
||||
<div className="h-4 w-4 animate-pulse rounded bg-neutral-200" />
|
||||
<div className="h-4 w-4 animate-pulse rounded bg-neutral-200" />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
{data?.map((item, key) => (
|
||||
<div
|
||||
key={key}
|
||||
@@ -12,11 +59,47 @@ export default function StateSection() {
|
||||
>
|
||||
<h1>{item.topic}</h1>
|
||||
<div className="flex gap-2 ">
|
||||
<Edit className="text-blue-500 cursor-pointer" size={18} />
|
||||
<Trash2 className="text-red-500 cursor-pointer" size={18} />
|
||||
<Edit className="text-neutral-300" size={18} />
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleDelete(item.topic)}
|
||||
className="text-red-500 disabled:cursor-not-allowed disabled:opacity-60"
|
||||
disabled={deleteTopic.isPending}
|
||||
aria-label={`Hapus topic ${item.topic}`}
|
||||
>
|
||||
<Trash2 size={18} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
{pending.open && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4">
|
||||
<div className="w-full max-w-sm rounded-md bg-white p-4 shadow-lg transition-all duration-200 ease-out">
|
||||
<h3 className="text-base font-semibold">Hapus Topic</h3>
|
||||
<p className="mt-2 text-sm text-neutral-600">
|
||||
Yakin ingin menghapus topic "{pending.topic}"?
|
||||
</p>
|
||||
<div className="mt-4 flex justify-end gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleClose}
|
||||
className="rounded-md border border-neutral-300 px-4 py-2 text-sm"
|
||||
disabled={deleteTopic.isPending}
|
||||
>
|
||||
Batal
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleConfirmDelete}
|
||||
className="rounded-md bg-red-500 px-4 py-2 text-sm text-white disabled:cursor-not-allowed disabled:opacity-70"
|
||||
disabled={deleteTopic.isPending}
|
||||
>
|
||||
{deleteTopic.isPending ? "Menghapus..." : "Hapus"}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user