Files
smart-home/src/features/topics/sections/state.tsx

106 lines
3.5 KiB
TypeScript

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, 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}
className="bg-white border-b border-neutral-200 p-4 flex justify-between"
>
<h1>{item.topic}</h1>
<div className="flex gap-2 ">
<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>
)}
</>
);
}