web-campaignpool/components/dialog/media-online.tsx

178 lines
5.8 KiB
TypeScript
Raw Normal View History

2025-11-11 02:52:38 +00:00
import { useState, useMemo } from "react";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogFooter,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
export default function DialogMediaOnline({
isOpen,
onClose,
}: {
isOpen: boolean;
onClose: () => void;
}) {
const mediaOnlineList = [
"Tribrata News Mabes",
"Tribrata News Polda Aceh",
"Tribrata News Polda Sumatera Utara",
"Tribrata News Polda Sumatera Barat",
"Tribrata News Polda Riau",
"Tribrata News Polda Kep. Riau",
"Tribrata News Polda Jambi",
"Tribrata News Polda Bengkulu",
"Tribrata News Polda Lampung",
"Tribrata News Polda Banten",
"Tribrata News Polda Metro Jaya",
"Tribrata News Polda Jawa Barat",
"Tribrata News Polda Jawa Tengah",
"Tribrata News Polda D.I Yogyakarta",
"Tribrata News Polda Jawa Timur",
"Tribrata News Polda Bali",
"Tribrata News Polda Nusa Tenggara Barat",
"Tribrata News Polda Nusa Tenggara Timur",
"Tribrata News Polda Kalimantan Barat",
"Tribrata News Polda Kalimantan Tengah",
"Tribrata News Polda Kalimantan Selatan",
"Tribrata News Polda Kalimantan Timur",
"Tribrata News Polda Kalimantan Utara",
"Tribrata News Polda Sulawesi Utara",
"Tribrata News Polda Gorontalo",
"Tribrata News Polda Sulawesi Tengah",
"Tribrata News Polda Sulawesi Barat",
"Tribrata News Polda Sulawesi Selatan",
"Tribrata News Polda Sulawesi Tenggara",
"Tribrata News Polda Maluku",
"Tribrata News Polda Maluku Utara",
"Tribrata News Polda Papua",
"Tribrata News Polda Papua Barat",
];
const [selectedMediaOnline, setSelectedMediaOnline] = useState<string[]>([]);
const [searchTerm, setSearchTerm] = useState("");
// 🔍 Filter media berdasarkan pencarian
const filteredMedia = useMemo(() => {
return mediaOnlineList.filter((item) =>
item.toLowerCase().includes(searchTerm.toLowerCase())
);
}, [searchTerm]);
// ✅ Toggle media
const toggleMediaOnline = (item: string) => {
setSelectedMediaOnline((prev) =>
prev.includes(item) ? prev.filter((m) => m !== item) : [...prev, item]
);
};
// ✅ Pilih semua
const toggleSelectAll = () => {
if (selectedMediaOnline.length === mediaOnlineList.length) {
setSelectedMediaOnline([]);
} else {
setSelectedMediaOnline(mediaOnlineList);
}
};
return (
<Dialog open={isOpen} onOpenChange={onClose}>
<DialogContent className="w-full max-w-3xl sm:max-h-[90vh] overflow-hidden flex flex-col">
<DialogHeader>
<DialogTitle>Pilih Media Online</DialogTitle>
</DialogHeader>
{/* 🔍 Input Cari */}
<div className="relative mb-4">
<input
type="text"
placeholder="Cari Media Online..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="w-full pl-10 pr-4 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<svg
xmlns="http://www.w3.org/2000/svg"
className="w-4 h-4 absolute left-3 top-3 text-gray-400"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M21 21l-4.35-4.35m0 0A7.5 7.5 0 104.5 4.5a7.5 7.5 0 0012.15 12.15z"
/>
</svg>
</div>
{/* ✅ Konten scrollable */}
<div className="flex-1 overflow-y-auto border rounded-md p-2 space-y-2">
<label className="flex items-center gap-2 p-2 rounded-md hover:bg-gray-50 cursor-pointer font-medium sticky top-0 bg-white z-10 border-b">
<input
type="checkbox"
checked={selectedMediaOnline.length === mediaOnlineList.length}
onChange={toggleSelectAll}
className="accent-blue-600"
/>
Pilih semua Media Online
</label>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2">
{filteredMedia.map((item) => (
<label
key={item}
className="flex items-center gap-2 p-2 rounded-md hover:bg-gray-50 cursor-pointer"
>
<input
type="checkbox"
checked={selectedMediaOnline.includes(item)}
onChange={() => toggleMediaOnline(item)}
className="accent-blue-600"
/>
<span>{item}</span>
</label>
))}
</div>
</div>
{/* 🏷️ Tag Media Terpilih (scrollable juga bila panjang) */}
{selectedMediaOnline.length > 0 && (
<div className="mt-3">
<p className="text-sm font-medium mb-2">
{selectedMediaOnline.length} Media Online dipilih
</p>
<div className="flex flex-wrap gap-2 max-h-[100px] overflow-y-auto border rounded-md p-2 bg-gray-50">
{selectedMediaOnline.map((m) => (
<div
key={m}
className="flex items-center gap-2 px-3 py-1 bg-white rounded-full text-sm border"
>
{m}
<button
onClick={() => toggleMediaOnline(m)}
className="text-gray-500 hover:text-gray-700"
>
</button>
</div>
))}
</div>
</div>
)}
{/* 🔘 Tombol Footer */}
<DialogFooter className="mt-4">
<Button variant="outline" onClick={onClose}>
Batal
</Button>
<Button onClick={onClose}>Pilih</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}