2025-11-11 02:52:38 +00:00
|
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
|
|
import { useState } from "react";
|
|
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
|
|
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
|
|
|
|
|
import { Label } from "@/components/ui/label";
|
|
|
|
|
|
import { Calendar } from "@/components/ui/calendar";
|
|
|
|
|
|
import {
|
|
|
|
|
|
Popover,
|
|
|
|
|
|
PopoverContent,
|
|
|
|
|
|
PopoverTrigger,
|
|
|
|
|
|
} from "@/components/ui/popover";
|
|
|
|
|
|
import {
|
|
|
|
|
|
Dialog,
|
|
|
|
|
|
DialogContent,
|
|
|
|
|
|
DialogHeader,
|
|
|
|
|
|
DialogTitle,
|
|
|
|
|
|
DialogFooter,
|
|
|
|
|
|
} from "@/components/ui/dialog";
|
|
|
|
|
|
import { Input } from "@/components/ui/input";
|
|
|
|
|
|
import { CalendarIcon, Plus, Trash2 } from "lucide-react";
|
|
|
|
|
|
import { format } from "date-fns";
|
|
|
|
|
|
import { id } from "date-fns/locale";
|
|
|
|
|
|
import { Progress } from "../ui/progress";
|
|
|
|
|
|
import DialogMediaOnline from "../dialog/media-online";
|
|
|
|
|
|
import DialogMediaSosial from "../dialog/media-sosial";
|
2026-04-14 07:51:47 +00:00
|
|
|
|
import MapVideotron from "../global/maps";
|
|
|
|
|
|
import dynamic from "next/dynamic";
|
2025-11-11 02:52:38 +00:00
|
|
|
|
|
|
|
|
|
|
export default function FormCampaign() {
|
|
|
|
|
|
const [startDate, setStartDate] = useState<Date | undefined>(undefined);
|
|
|
|
|
|
const [endDate, setEndDate] = useState<Date | undefined>(undefined);
|
|
|
|
|
|
const [goal, setGoal] = useState("Publikasi");
|
|
|
|
|
|
const [available, setAvailable] = useState("Yes");
|
|
|
|
|
|
const [isUploadOpen, setIsUploadOpen] = useState(false);
|
|
|
|
|
|
const [media, setMedia] = useState("Media Online");
|
|
|
|
|
|
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
|
|
|
|
|
2026-04-14 07:51:47 +00:00
|
|
|
|
const MapVideotron = dynamic(() => import("../global/maps"), {
|
|
|
|
|
|
ssr: false,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-11-11 02:52:38 +00:00
|
|
|
|
// contoh data pilihan media online (bisa diganti sesuai kebutuhan)
|
|
|
|
|
|
const mediaOnlineList = [
|
|
|
|
|
|
"Tribrata News Mabes",
|
|
|
|
|
|
"Tribrata News Polda Aceh",
|
|
|
|
|
|
"Tribrata News Polda Jawa Timur",
|
|
|
|
|
|
"Tribrata News Polda Jawa Tengah",
|
|
|
|
|
|
"Tribrata News Polda Jawa Barat",
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
const [selectedMediaOnline, setSelectedMediaOnline] = useState<string[]>([]);
|
2026-04-14 07:51:47 +00:00
|
|
|
|
const [contentType, setContentType] = useState("Meme");
|
|
|
|
|
|
const [talkshowType, setTalkshowType] = useState("Renjani Nyrah");
|
|
|
|
|
|
const [musicType, setMusicType] = useState("Sendrasena");
|
2025-11-11 02:52:38 +00:00
|
|
|
|
|
|
|
|
|
|
const toggleMediaOnline = (item: string) => {
|
|
|
|
|
|
setSelectedMediaOnline((prev) =>
|
2026-04-14 07:51:47 +00:00
|
|
|
|
prev.includes(item) ? prev.filter((m) => m !== item) : [...prev, item],
|
2025-11-11 02:52:38 +00:00
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const [files, setFiles] = useState<
|
|
|
|
|
|
{ file: File; progress: number; uploaded: boolean }[]
|
|
|
|
|
|
>([]);
|
|
|
|
|
|
const [url, setUrl] = useState("");
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Upload dari file input
|
|
|
|
|
|
const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
|
|
|
|
const selectedFiles = e.target.files;
|
|
|
|
|
|
if (!selectedFiles) return;
|
|
|
|
|
|
|
|
|
|
|
|
const newFiles = Array.from(selectedFiles).map((f) => ({
|
|
|
|
|
|
file: f,
|
|
|
|
|
|
progress: 0,
|
|
|
|
|
|
uploaded: false,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
setFiles((prev) => [...prev, ...newFiles]);
|
|
|
|
|
|
simulateUpload(newFiles);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Simulasi upload progress
|
|
|
|
|
|
const simulateUpload = (
|
2026-04-14 07:51:47 +00:00
|
|
|
|
fileList: { file: File; progress: number; uploaded: boolean }[],
|
2025-11-11 02:52:38 +00:00
|
|
|
|
) => {
|
|
|
|
|
|
fileList.forEach((fileObj) => {
|
|
|
|
|
|
let progress = 0;
|
|
|
|
|
|
const interval = setInterval(() => {
|
|
|
|
|
|
progress += 10;
|
|
|
|
|
|
setFiles((prev) =>
|
|
|
|
|
|
prev.map((f) =>
|
|
|
|
|
|
f.file === fileObj.file
|
|
|
|
|
|
? { ...f, progress, uploaded: progress >= 100 }
|
2026-04-14 07:51:47 +00:00
|
|
|
|
: f,
|
|
|
|
|
|
),
|
2025-11-11 02:52:38 +00:00
|
|
|
|
);
|
|
|
|
|
|
if (progress >= 100) clearInterval(interval);
|
|
|
|
|
|
}, 300);
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Upload dari URL
|
|
|
|
|
|
const handleUploadFromUrl = () => {
|
|
|
|
|
|
if (!url.trim()) return;
|
|
|
|
|
|
const fakeFile = {
|
|
|
|
|
|
file: new File([], url.split("/").pop() || "file_from_url.jpg"),
|
|
|
|
|
|
progress: 100,
|
|
|
|
|
|
uploaded: true,
|
|
|
|
|
|
};
|
|
|
|
|
|
setFiles((prev) => [...prev, fakeFile]);
|
|
|
|
|
|
setUrl("");
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Hapus file
|
|
|
|
|
|
const removeFile = (index: number) => {
|
|
|
|
|
|
setFiles((prev) => prev.filter((_, i) => i !== index));
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div className="bg-white rounded-2xl shadow-sm p-6 space-y-8">
|
|
|
|
|
|
{/* Langkah 1 */}
|
|
|
|
|
|
<section className="border-b pb-6">
|
|
|
|
|
|
<h2 className="font-semibold mb-4">Langkah 1</h2>
|
|
|
|
|
|
<p className="text-sm font-medium mb-2">Pilih Durasi</p>
|
|
|
|
|
|
<div className="flex flex-wrap gap-4">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<Label className="text-sm">Dari Tanggal</Label>
|
|
|
|
|
|
<Popover>
|
|
|
|
|
|
<PopoverTrigger asChild>
|
|
|
|
|
|
<Button
|
|
|
|
|
|
variant="outline"
|
|
|
|
|
|
className="w-[200px] justify-start text-left font-normal"
|
|
|
|
|
|
>
|
|
|
|
|
|
<CalendarIcon className="mr-2 h-4 w-4" />
|
|
|
|
|
|
{startDate
|
|
|
|
|
|
? format(startDate, "dd MMMM yyyy", { locale: id })
|
|
|
|
|
|
: "Pilih tanggal"}
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</PopoverTrigger>
|
|
|
|
|
|
<PopoverContent className="p-0" align="start">
|
|
|
|
|
|
<Calendar
|
|
|
|
|
|
mode="single"
|
|
|
|
|
|
selected={startDate}
|
|
|
|
|
|
onSelect={setStartDate}
|
|
|
|
|
|
locale={id}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</PopoverContent>
|
|
|
|
|
|
</Popover>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<Label className="text-sm">Sampai Tanggal</Label>
|
|
|
|
|
|
<Popover>
|
|
|
|
|
|
<PopoverTrigger asChild>
|
|
|
|
|
|
<Button
|
|
|
|
|
|
variant="outline"
|
|
|
|
|
|
className="w-[200px] justify-start text-left font-normal"
|
|
|
|
|
|
>
|
|
|
|
|
|
<CalendarIcon className="mr-2 h-4 w-4" />
|
|
|
|
|
|
{endDate
|
|
|
|
|
|
? format(endDate, "dd MMMM yyyy", { locale: id })
|
|
|
|
|
|
: "Pilih tanggal"}
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</PopoverTrigger>
|
|
|
|
|
|
<PopoverContent className="p-0" align="start">
|
|
|
|
|
|
<Calendar
|
|
|
|
|
|
mode="single"
|
|
|
|
|
|
selected={endDate}
|
|
|
|
|
|
onSelect={setEndDate}
|
|
|
|
|
|
locale={id}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</PopoverContent>
|
|
|
|
|
|
</Popover>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<section className="border-b pb-6">
|
|
|
|
|
|
<h2 className="font-semibold mb-4">Langkah 2</h2>
|
|
|
|
|
|
<p className="text-sm font-medium mb-2">Pilih Media</p>
|
|
|
|
|
|
|
|
|
|
|
|
<RadioGroup
|
|
|
|
|
|
value={media}
|
|
|
|
|
|
onValueChange={setMedia}
|
|
|
|
|
|
className="flex flex-wrap gap-4"
|
|
|
|
|
|
>
|
|
|
|
|
|
{[
|
|
|
|
|
|
"Media Online",
|
|
|
|
|
|
"Media Sosial",
|
|
|
|
|
|
"Videotron",
|
|
|
|
|
|
"Radio Polri",
|
|
|
|
|
|
"TV Polri",
|
|
|
|
|
|
"Majalah Digital",
|
|
|
|
|
|
].map((m) => (
|
|
|
|
|
|
<div key={m} className="flex items-center space-x-2">
|
|
|
|
|
|
<RadioGroupItem value={m} id={m} />
|
|
|
|
|
|
<Label htmlFor={m}>{m}</Label>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</RadioGroup>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Tombol muncul sesuai media terpilih */}
|
|
|
|
|
|
{media === "Media Online" && (
|
|
|
|
|
|
<Button
|
|
|
|
|
|
variant="outline"
|
|
|
|
|
|
size="sm"
|
|
|
|
|
|
className="mt-4"
|
|
|
|
|
|
onClick={() => setIsDialogOpen(true)}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
|
|
|
|
Tambahkan Media Online
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
|
|
{media === "Media Sosial" && (
|
|
|
|
|
|
<Button
|
|
|
|
|
|
variant="outline"
|
|
|
|
|
|
size="sm"
|
|
|
|
|
|
className="mt-4"
|
|
|
|
|
|
onClick={() => setIsDialogOpen(true)}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
|
|
|
|
Tambahkan Media Sosial
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
)}
|
|
|
|
|
|
{media === "Videotron" && (
|
2026-04-14 07:51:47 +00:00
|
|
|
|
<div className="mt-4 space-y-4">
|
|
|
|
|
|
{/* Map tampil */}
|
|
|
|
|
|
<MapVideotron />
|
|
|
|
|
|
</div>
|
2025-11-11 02:52:38 +00:00
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
|
|
{/* 🧩 Komponen DialogMediaOnline dipanggil di sini */}
|
|
|
|
|
|
{media === "Media Online" && (
|
|
|
|
|
|
<DialogMediaOnline
|
|
|
|
|
|
isOpen={isDialogOpen}
|
|
|
|
|
|
onClose={() => setIsDialogOpen(false)}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
{media === "Media Sosial" && (
|
|
|
|
|
|
<DialogMediaSosial
|
|
|
|
|
|
isOpen={isDialogOpen}
|
|
|
|
|
|
onClose={() => setIsDialogOpen(false)}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
{media === "Videotron" && (
|
|
|
|
|
|
<DialogMediaSosial
|
|
|
|
|
|
isOpen={isDialogOpen}
|
|
|
|
|
|
onClose={() => setIsDialogOpen(false)}
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
{media === "Radio Polri" && (
|
|
|
|
|
|
<div className="mt-4 space-y-3">
|
|
|
|
|
|
{[
|
|
|
|
|
|
"Pagi pukul 06:00 – 07:00",
|
|
|
|
|
|
"Siang pukul 12:00 – 13:00",
|
|
|
|
|
|
"Sore pukul 16:00 – 17:00",
|
|
|
|
|
|
"Malam pukul 20:00 – 21:00",
|
|
|
|
|
|
].map((time) => (
|
|
|
|
|
|
<div key={time} className="flex items-center space-x-2">
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="checkbox"
|
|
|
|
|
|
id={time}
|
|
|
|
|
|
value={time}
|
|
|
|
|
|
className="w-4 h-4 border border-purple-600 text-purple-600 focus:ring-2 focus:ring-purple-500 rounded"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<Label htmlFor={time} className="text-sm">
|
|
|
|
|
|
{time}
|
|
|
|
|
|
</Label>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
{media === "TV Polri" && (
|
|
|
|
|
|
<div className="mt-4 space-y-3">
|
|
|
|
|
|
{[
|
|
|
|
|
|
"Pagi pukul 06:00 – 07:00",
|
|
|
|
|
|
"Siang pukul 12:00 – 13:00",
|
|
|
|
|
|
"Sore pukul 16:00 – 17:00",
|
|
|
|
|
|
"Malam pukul 20:00 – 21:00",
|
|
|
|
|
|
].map((time) => (
|
|
|
|
|
|
<div key={time} className="flex items-center space-x-2">
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="checkbox"
|
|
|
|
|
|
id={time}
|
|
|
|
|
|
value={time}
|
|
|
|
|
|
className="w-4 h-4 border border-purple-600 text-purple-600 focus:ring-2 focus:ring-purple-500 rounded"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<Label htmlFor={time} className="text-sm">
|
|
|
|
|
|
{time}
|
|
|
|
|
|
</Label>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Langkah 3 */}
|
|
|
|
|
|
<section className="border-b pb-6">
|
|
|
|
|
|
<h2 className="font-semibold mb-4">Langkah 3</h2>
|
|
|
|
|
|
<p className="text-sm font-medium mb-2">Tujuan</p>
|
|
|
|
|
|
<RadioGroup value={goal} onValueChange={setGoal} className="flex gap-4">
|
|
|
|
|
|
{["Publikasi", "Sosialisasi"].map((g) => (
|
|
|
|
|
|
<div key={g} className="flex items-center space-x-2">
|
|
|
|
|
|
<RadioGroupItem value={g} id={g} />
|
|
|
|
|
|
<Label htmlFor={g}>{g}</Label>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</RadioGroup>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Langkah 4 */}
|
|
|
|
|
|
<section>
|
|
|
|
|
|
<h2 className="font-semibold mb-4">Langkah 4</h2>
|
|
|
|
|
|
<p className="text-sm font-medium mb-2">Materi Promote Tersedia</p>
|
|
|
|
|
|
|
|
|
|
|
|
<RadioGroup
|
|
|
|
|
|
value={available}
|
|
|
|
|
|
onValueChange={setAvailable}
|
|
|
|
|
|
className="flex gap-4 mb-4"
|
|
|
|
|
|
>
|
|
|
|
|
|
{["Yes", "Tidak"].map((a) => (
|
|
|
|
|
|
<div key={a} className="flex items-center space-x-2">
|
|
|
|
|
|
<RadioGroupItem value={a} id={a} />
|
|
|
|
|
|
<Label htmlFor={a}>{a}</Label>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</RadioGroup>
|
|
|
|
|
|
|
|
|
|
|
|
{available === "Yes" ? (
|
2026-04-14 07:51:47 +00:00
|
|
|
|
// ✅ Upload
|
2025-11-11 02:52:38 +00:00
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
|
<Label className="text-sm font-medium">Upload File</Label>
|
2026-04-14 07:51:47 +00:00
|
|
|
|
<Button
|
|
|
|
|
|
variant="outline"
|
|
|
|
|
|
size="sm"
|
|
|
|
|
|
onClick={() => setIsUploadOpen(true)}
|
|
|
|
|
|
>
|
|
|
|
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
|
|
|
|
Upload File
|
|
|
|
|
|
</Button>
|
2025-11-11 02:52:38 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
) : (
|
2026-04-14 07:51:47 +00:00
|
|
|
|
// ❌ Tidak → tampil pilihan konten
|
|
|
|
|
|
<div className="space-y-4">
|
|
|
|
|
|
{/* Pilih Jenis Konten */}
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<p className="text-sm font-medium mb-2">Pilih Jenis Konten</p>
|
|
|
|
|
|
|
|
|
|
|
|
<RadioGroup
|
|
|
|
|
|
value={contentType}
|
|
|
|
|
|
onValueChange={setContentType}
|
|
|
|
|
|
className="flex flex-wrap gap-4"
|
|
|
|
|
|
>
|
|
|
|
|
|
{["Meme", "AI Influencer", "Talkshow", "Musik"].map((item) => (
|
|
|
|
|
|
<div key={item} className="flex items-center space-x-2">
|
|
|
|
|
|
<RadioGroupItem value={item} id={item} />
|
|
|
|
|
|
<Label htmlFor={item}>{item}</Label>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</RadioGroup>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* List Konten (Dummy) */}
|
|
|
|
|
|
{/* List Konten */}
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<p className="text-sm font-medium mb-2">Pilih {contentType}</p>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 🔥 TAMPILAN KHUSUS MEME */}
|
|
|
|
|
|
{contentType === "Meme" && (
|
|
|
|
|
|
<div className="space-y-4">
|
|
|
|
|
|
{/* Search */}
|
|
|
|
|
|
<div className="relative">
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
placeholder="Cari Meme..."
|
|
|
|
|
|
className="w-full pl-10 pr-4 py-2 border rounded-full text-sm"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<span className="absolute left-3 top-2.5 text-gray-400 text-sm">
|
|
|
|
|
|
🔍
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Grid Meme */}
|
|
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-4">
|
|
|
|
|
|
{[
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/meme1.png",
|
|
|
|
|
|
title:
|
|
|
|
|
|
"Respons Cepat Lakukan Sterilisasi Ancaman Bom di Depok",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/meme2.png",
|
|
|
|
|
|
title: "Upacara Penutupan Pendidikan Anggota Polri",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/meme3.png",
|
|
|
|
|
|
title: "Pantau Situasi Kamtibmas Malam Natal",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/meme4.png",
|
|
|
|
|
|
title: "Program SPPG Bersama Penerima Manfaat",
|
|
|
|
|
|
},
|
|
|
|
|
|
].map((item, i) => (
|
|
|
|
|
|
<div
|
|
|
|
|
|
key={i}
|
|
|
|
|
|
className="bg-white border rounded-xl overflow-hidden shadow-sm hover:shadow-md"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div className="relative">
|
|
|
|
|
|
<img
|
|
|
|
|
|
src={item.img}
|
|
|
|
|
|
className="w-full h-40 object-cover"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="checkbox"
|
|
|
|
|
|
className="absolute top-2 left-2 w-4 h-4"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<div className="absolute bottom-2 right-2 text-white text-xs bg-black/50 px-1 rounded">
|
|
|
|
|
|
⛶
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div className="p-2 text-xs line-clamp-2">
|
|
|
|
|
|
{item.title}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
|
|
{contentType === "AI Influencer" && (
|
|
|
|
|
|
<div className="space-y-4">
|
|
|
|
|
|
{/* Search */}
|
|
|
|
|
|
<div className="relative">
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
placeholder="Cari AI Influencer..."
|
|
|
|
|
|
className="w-full pl-10 pr-4 py-2 border rounded-full text-sm"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<span className="absolute left-3 top-2.5 text-gray-400 text-sm">
|
|
|
|
|
|
🔍
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Grid AI */}
|
|
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-4">
|
|
|
|
|
|
{[
|
|
|
|
|
|
{ img: "/ai1.png", name: "Revandra Jaya" },
|
|
|
|
|
|
{ img: "/ai2.png", name: "Fudhalina Adisty" },
|
|
|
|
|
|
{ img: "/ai3.png", name: "Adriyan Pratama" },
|
|
|
|
|
|
{ img: "/ai4.png", name: "Nadhya Wijaya" },
|
|
|
|
|
|
].map((item, i) => (
|
|
|
|
|
|
<div
|
|
|
|
|
|
key={i}
|
|
|
|
|
|
className="relative rounded-xl overflow-hidden shadow-sm hover:shadow-md"
|
|
|
|
|
|
>
|
|
|
|
|
|
{/* Image */}
|
|
|
|
|
|
<img
|
|
|
|
|
|
src={item.img}
|
|
|
|
|
|
className="w-full h-48 object-cover"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Overlay bawah */}
|
|
|
|
|
|
<div className="absolute bottom-0 left-0 right-0 bg-white/80 backdrop-blur px-3 py-2 flex items-center gap-2">
|
|
|
|
|
|
<input type="checkbox" className="w-4 h-4" />
|
|
|
|
|
|
<span className="text-xs font-medium">
|
|
|
|
|
|
{item.name}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Footer */}
|
|
|
|
|
|
<div className="flex justify-end items-center text-xs text-gray-500 gap-4">
|
|
|
|
|
|
<span>Rows per page: 1</span>
|
|
|
|
|
|
<span>1-1 of 1</span>
|
|
|
|
|
|
<div className="flex gap-2">
|
|
|
|
|
|
<button>{"<"}</button>
|
|
|
|
|
|
<button>{">"}</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
{contentType === "Talkshow" && (
|
|
|
|
|
|
<div className="space-y-4">
|
|
|
|
|
|
{/* Select Talkshow */}
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<p className="text-sm font-medium mb-2">Pilih Talkshow</p>
|
|
|
|
|
|
|
|
|
|
|
|
<select
|
|
|
|
|
|
value={talkshowType}
|
|
|
|
|
|
onChange={(e) => setTalkshowType(e.target.value)}
|
|
|
|
|
|
className="border rounded-md px-3 py-2 text-sm"
|
|
|
|
|
|
>
|
|
|
|
|
|
<option value="Renjani Nyrah">Renjani Nyrah</option>
|
|
|
|
|
|
<option value="Agatha Bicara">Agatha Bicara</option>
|
|
|
|
|
|
</select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Konten berdasarkan pilihan */}
|
|
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
|
|
|
|
|
|
{(talkshowType === "Renjani Nyrah"
|
|
|
|
|
|
? [
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/ts1.jpg",
|
|
|
|
|
|
title: "Renjani Nyrah - Napak Tilas di Museum",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/ts2.jpg",
|
|
|
|
|
|
title: "Renjani Nyrah - Kata Kata Baru",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/ts3.jpg",
|
|
|
|
|
|
title: "Renjani Nyrah - Pestapora 2025",
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
: [
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/agatha1.jpg",
|
|
|
|
|
|
title: "Agatha Bicara - Kerja DPR Itu Apa?",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/agatha1.jpg",
|
|
|
|
|
|
title: "Agatha Bicara - Kerja DPR Itu Apa?",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/agatha2.png",
|
|
|
|
|
|
title: "Agatha Bicara - Penghargaan dari Presiden",
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
).map((item, i) => (
|
|
|
|
|
|
<div
|
|
|
|
|
|
key={i}
|
|
|
|
|
|
className="bg-white border rounded-xl overflow-hidden shadow-sm hover:shadow-md"
|
|
|
|
|
|
>
|
|
|
|
|
|
{/* Image */}
|
|
|
|
|
|
<div className="relative">
|
|
|
|
|
|
<img
|
|
|
|
|
|
src={item.img}
|
|
|
|
|
|
className="w-full h-40 object-cover"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Checkbox */}
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="checkbox"
|
|
|
|
|
|
className="absolute top-2 left-2 w-4 h-4"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Expand icon */}
|
|
|
|
|
|
<div className="absolute bottom-2 right-2 text-white text-xs bg-black/50 px-1 rounded">
|
|
|
|
|
|
⛶
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Title */}
|
|
|
|
|
|
<div className="p-2 text-xs line-clamp-2">
|
|
|
|
|
|
{item.title}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
{contentType === "Musik" && (
|
|
|
|
|
|
<div className="space-y-4">
|
|
|
|
|
|
{/* Dropdown Musik */}
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<p className="text-sm font-medium mb-2">Pilih Musik</p>
|
|
|
|
|
|
|
|
|
|
|
|
<select
|
|
|
|
|
|
value={musicType}
|
|
|
|
|
|
onChange={(e) => setMusicType(e.target.value)}
|
|
|
|
|
|
className="border rounded-md px-3 py-2 text-sm"
|
|
|
|
|
|
>
|
|
|
|
|
|
<option value="Sendrasena">Sendrasena</option>
|
|
|
|
|
|
<option value="Selara Luna">Selara Luna</option>
|
|
|
|
|
|
</select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Grid Musik */}
|
|
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-4">
|
|
|
|
|
|
{(musicType === "Sendrasena"
|
|
|
|
|
|
? [
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/m1.jpg",
|
|
|
|
|
|
title: "Sendrasena - Track 1",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/m2.jpg",
|
|
|
|
|
|
title: "Sendrasena - Track 2",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/m3.jpg",
|
|
|
|
|
|
title: "Sendrasena - Track 3",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/m4.jpg",
|
|
|
|
|
|
title: "Sendrasena - Track 4",
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
: [
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/sl1.jpg",
|
|
|
|
|
|
title: "Selara Luna - Track 1",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/sl2.jpg",
|
|
|
|
|
|
title: "Selara Luna - Track 2",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/sl3.jpg",
|
|
|
|
|
|
title: "Selara Luna - Track 3",
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
img: "/sl4.jpg",
|
|
|
|
|
|
title: "Selara Luna - Track 4",
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
).map((item, i) => (
|
|
|
|
|
|
<div
|
|
|
|
|
|
key={i}
|
|
|
|
|
|
className="bg-white border rounded-xl overflow-hidden shadow-sm hover:shadow-md"
|
|
|
|
|
|
>
|
|
|
|
|
|
{/* Cover */}
|
|
|
|
|
|
<div className="relative">
|
|
|
|
|
|
<img
|
|
|
|
|
|
src={item.img}
|
|
|
|
|
|
className="w-full h-40 object-cover"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Checkbox */}
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="checkbox"
|
|
|
|
|
|
className="absolute top-2 left-2 w-4 h-4"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Play icon (biar beda dari talkshow 😄) */}
|
|
|
|
|
|
<div className="absolute bottom-2 right-2 text-white text-xs bg-black/50 px-2 py-1 rounded">
|
|
|
|
|
|
▶
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Title */}
|
|
|
|
|
|
<div className="p-2 text-xs line-clamp-2">
|
|
|
|
|
|
{item.title}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
2025-11-11 02:52:38 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<div className="pt-6">
|
|
|
|
|
|
<Button className="w-[120px]" size="lg">
|
|
|
|
|
|
Submit
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* Modal Upload */}
|
|
|
|
|
|
<Dialog open={isUploadOpen} onOpenChange={setIsUploadOpen}>
|
|
|
|
|
|
<DialogContent className="max-w-lg w-[90vw] sm:w-full">
|
|
|
|
|
|
<DialogHeader>
|
|
|
|
|
|
<DialogTitle>Unggah Berkas</DialogTitle>
|
|
|
|
|
|
<p className="text-sm text-muted-foreground">
|
|
|
|
|
|
Pilih berkas dan unggah dengan aman untuk melanjutkan.
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</DialogHeader>
|
|
|
|
|
|
|
|
|
|
|
|
{/* === Upload Section === */}
|
|
|
|
|
|
<div className="border-2 border-dashed rounded-lg p-6 flex flex-col items-center justify-center text-center space-y-2 w-full">
|
|
|
|
|
|
<p className="text-sm text-muted-foreground">
|
|
|
|
|
|
Seret dan jatuhkan berkas Anda
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<p className="text-xs text-muted-foreground">
|
|
|
|
|
|
Format .PNG, .JPG, dan .JPEG hingga 50MB
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<label htmlFor="fileInput">
|
|
|
|
|
|
<Button
|
|
|
|
|
|
variant="outline"
|
|
|
|
|
|
size="sm"
|
|
|
|
|
|
className="mt-2 cursor-pointer"
|
|
|
|
|
|
>
|
|
|
|
|
|
Pilih Berkas
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
<Input
|
|
|
|
|
|
id="fileInput"
|
|
|
|
|
|
type="file"
|
|
|
|
|
|
multiple
|
|
|
|
|
|
className="hidden"
|
|
|
|
|
|
onChange={handleFileUpload}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</label>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* === Upload via URL === */}
|
|
|
|
|
|
<div className="flex flex-col sm:flex-row items-center gap-2 mt-4 w-full">
|
|
|
|
|
|
<Input
|
|
|
|
|
|
type="url"
|
|
|
|
|
|
placeholder="Tambahkan URL berkas"
|
|
|
|
|
|
value={url}
|
|
|
|
|
|
onChange={(e) => setUrl(e.target.value)}
|
|
|
|
|
|
className="flex-1"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<Button onClick={handleUploadFromUrl} className="w-full sm:w-auto">
|
|
|
|
|
|
Unggah
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* === Uploaded Files === */}
|
|
|
|
|
|
{files.length > 0 && (
|
|
|
|
|
|
<div className="mt-5 space-y-3 max-h-[60vh] overflow-y-auto">
|
|
|
|
|
|
<h4 className="text-sm font-semibold">Uploaded Files</h4>
|
|
|
|
|
|
<div className="space-y-2">
|
|
|
|
|
|
{files.map((f, i) => (
|
|
|
|
|
|
<div
|
|
|
|
|
|
key={i}
|
|
|
|
|
|
className="border rounded-lg p-3 flex flex-wrap sm:flex-nowrap justify-between items-start sm:items-center gap-3"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div className="flex flex-col min-w-0 flex-1">
|
|
|
|
|
|
<p className="text-sm font-medium truncate max-w-[250px]">
|
|
|
|
|
|
{f.file.name}
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<p className="text-xs text-muted-foreground">
|
|
|
|
|
|
{(f.file.size / (1024 * 1024)).toFixed(1)}MB •{" "}
|
|
|
|
|
|
{f.uploaded ? (
|
|
|
|
|
|
<span className="text-green-600 font-medium">
|
|
|
|
|
|
Uploaded Successfully
|
|
|
|
|
|
</span>
|
|
|
|
|
|
) : (
|
|
|
|
|
|
<span className="text-blue-600 font-medium">
|
|
|
|
|
|
{f.progress}% • Uploading...
|
|
|
|
|
|
</span>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</p>
|
|
|
|
|
|
{!f.uploaded && (
|
|
|
|
|
|
<Progress
|
|
|
|
|
|
value={f.progress}
|
|
|
|
|
|
className="h-1 mt-1 w-full bg-gray-200"
|
|
|
|
|
|
/>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<Button
|
|
|
|
|
|
variant="ghost"
|
|
|
|
|
|
size="icon"
|
|
|
|
|
|
onClick={() => removeFile(i)}
|
|
|
|
|
|
className="shrink-0"
|
|
|
|
|
|
>
|
|
|
|
|
|
<Trash2 className="h-4 w-4 text-muted-foreground" />
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
|
|
<DialogFooter className="mt-4 flex flex-col sm:flex-row justify-end gap-2 sm:gap-4">
|
|
|
|
|
|
<Button
|
|
|
|
|
|
variant="outline"
|
|
|
|
|
|
onClick={() => setIsUploadOpen(false)}
|
|
|
|
|
|
className="w-full sm:w-auto"
|
|
|
|
|
|
>
|
|
|
|
|
|
Batal
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
<Button
|
|
|
|
|
|
onClick={() => setIsUploadOpen(false)}
|
|
|
|
|
|
className="w-full sm:w-auto"
|
|
|
|
|
|
>
|
|
|
|
|
|
Lampirkan Berkas
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
</DialogFooter>
|
|
|
|
|
|
</DialogContent>
|
|
|
|
|
|
</Dialog>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|