237 lines
7.4 KiB
TypeScript
237 lines
7.4 KiB
TypeScript
import { useState, useMemo } from "react";
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogFooter,
|
|
} from "@/components/ui/dialog";
|
|
import { Button } from "@/components/ui/button";
|
|
import { ChevronDown, ChevronUp } from "lucide-react";
|
|
|
|
export default function DialogMediaSosial({
|
|
isOpen,
|
|
onClose,
|
|
}: {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
}) {
|
|
const mediaPlatforms = ["X", "Instagram", "Facebook", "Youtube", "TikTok"];
|
|
|
|
const mediaPerPlatform: Record<string, string[]> = {
|
|
X: ["X Mabes", "X Polda Jawa Timur", "X Polda Jawa Barat"],
|
|
Instagram: [
|
|
"Instagram Mabes",
|
|
"Instagram Polda Jawa Timur",
|
|
"Instagram Polda Jawa Barat",
|
|
],
|
|
Facebook: [
|
|
"Facebook Mabes",
|
|
"Facebook Polda Jawa Timur",
|
|
"Facebook Polda Jawa Barat",
|
|
],
|
|
Youtube: [
|
|
"Youtube Mabes",
|
|
"Youtube Polda Jawa Timur",
|
|
"Youtube Polda Jawa Barat",
|
|
],
|
|
TikTok: [
|
|
"TikTok Mabes",
|
|
"TikTok Polda Jawa Timur",
|
|
"TikTok Polda Jawa Barat",
|
|
],
|
|
};
|
|
|
|
const [selectedMediaSosial, setSelectedMediaSosial] = useState<string[]>([]);
|
|
const [searchTerm, setSearchTerm] = useState("");
|
|
const [expanded, setExpanded] = useState<Record<string, boolean>>({});
|
|
const [selectedPlatforms, setSelectedPlatforms] = useState<string[]>([
|
|
"X",
|
|
"Instagram",
|
|
"Facebook",
|
|
"Youtube",
|
|
"TikTok",
|
|
]);
|
|
|
|
// Filter berdasarkan pencarian
|
|
const filteredPlatforms = useMemo(() => {
|
|
return mediaPlatforms.filter((p) =>
|
|
p.toLowerCase().includes(searchTerm.toLowerCase())
|
|
);
|
|
}, [searchTerm]);
|
|
|
|
// Toggle platform (misalnya centang Instagram)
|
|
const togglePlatform = (platform: string) => {
|
|
if (selectedPlatforms.includes(platform)) {
|
|
setSelectedPlatforms(selectedPlatforms.filter((p) => p !== platform));
|
|
// hapus semua media sosial di dalam platform tsb
|
|
setSelectedMediaSosial((prev) =>
|
|
prev.filter((m) => !mediaPerPlatform[platform].includes(m))
|
|
);
|
|
} else {
|
|
setSelectedPlatforms([...selectedPlatforms, platform]);
|
|
setSelectedMediaSosial((prev) => [
|
|
...prev,
|
|
...mediaPerPlatform[platform],
|
|
]);
|
|
}
|
|
};
|
|
|
|
// Toggle semua platform
|
|
const toggleSelectAll = () => {
|
|
if (selectedPlatforms.length === mediaPlatforms.length) {
|
|
setSelectedPlatforms([]);
|
|
setSelectedMediaSosial([]);
|
|
} else {
|
|
setSelectedPlatforms([...mediaPlatforms]);
|
|
setSelectedMediaSosial(Object.values(mediaPerPlatform).flat());
|
|
}
|
|
};
|
|
|
|
// Expand/collapse per platform
|
|
const toggleExpand = (platform: string) => {
|
|
setExpanded((prev) => ({ ...prev, [platform]: !prev[platform] }));
|
|
};
|
|
|
|
// Toggle media per item
|
|
const toggleMedia = (media: string) => {
|
|
setSelectedMediaSosial((prev) =>
|
|
prev.includes(media) ? prev.filter((m) => m !== media) : [...prev, media]
|
|
);
|
|
};
|
|
|
|
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 Sosial</DialogTitle>
|
|
</DialogHeader>
|
|
|
|
{/* Input Pencarian */}
|
|
<div className="relative mb-4">
|
|
<input
|
|
type="text"
|
|
placeholder="Cari Media Sosial..."
|
|
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>
|
|
|
|
{/* Checkbox utama */}
|
|
<div className="flex flex-wrap gap-3 mb-3">
|
|
<label className="flex items-center gap-2 font-medium cursor-pointer">
|
|
<input
|
|
type="checkbox"
|
|
checked={selectedPlatforms.length === mediaPlatforms.length}
|
|
onChange={toggleSelectAll}
|
|
className="accent-blue-600"
|
|
/>
|
|
Semua
|
|
</label>
|
|
|
|
{filteredPlatforms.map((platform) => (
|
|
<label
|
|
key={platform}
|
|
className="flex items-center gap-2 cursor-pointer"
|
|
>
|
|
<input
|
|
type="checkbox"
|
|
checked={selectedPlatforms.includes(platform)}
|
|
onChange={() => togglePlatform(platform)}
|
|
className="accent-blue-600"
|
|
/>
|
|
{platform}
|
|
</label>
|
|
))}
|
|
</div>
|
|
|
|
{/* Expand per platform */}
|
|
<div className="flex-1 overflow-y-auto border rounded-md p-2 space-y-1">
|
|
{filteredPlatforms.map((platform) => (
|
|
<div key={platform}>
|
|
<button
|
|
onClick={() => toggleExpand(platform)}
|
|
className="flex justify-between items-center w-full p-2 font-medium hover:bg-gray-50 rounded-md"
|
|
>
|
|
<span>Pilih {platform}</span>
|
|
{expanded[platform] ? (
|
|
<ChevronUp className="w-4 h-4" />
|
|
) : (
|
|
<ChevronDown className="w-4 h-4" />
|
|
)}
|
|
</button>
|
|
|
|
{expanded[platform] && (
|
|
<div className="pl-4 grid grid-cols-1 sm:grid-cols-2 gap-2 mt-1">
|
|
{mediaPerPlatform[platform].map((media) => (
|
|
<label
|
|
key={media}
|
|
className="flex items-center gap-2 p-2 rounded-md hover:bg-gray-50 cursor-pointer"
|
|
>
|
|
<input
|
|
type="checkbox"
|
|
checked={selectedMediaSosial.includes(media)}
|
|
onChange={() => toggleMedia(media)}
|
|
className="accent-blue-600"
|
|
/>
|
|
{media}
|
|
</label>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Tag media sosial dipilih */}
|
|
{selectedMediaSosial.length > 0 && (
|
|
<div className="mt-3">
|
|
<p className="text-sm font-medium mb-2">
|
|
{selectedMediaSosial.length} Media Sosial dipilih
|
|
</p>
|
|
<div className="flex flex-wrap gap-2 max-h-[100px] overflow-y-auto border rounded-md p-2 bg-gray-50">
|
|
{selectedMediaSosial.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={() => toggleMedia(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>
|
|
);
|
|
}
|