feat:agenda-setting admin, filter detail task
This commit is contained in:
parent
071040bdea
commit
c9592c0d25
|
|
@ -10,7 +10,7 @@ import { Label } from "@/components/ui/label";
|
||||||
import ExternalDraggingevent from "./dragging-events";
|
import ExternalDraggingevent from "./dragging-events";
|
||||||
import { Calendar } from "@/components/ui/calendar";
|
import { Calendar } from "@/components/ui/calendar";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Plus } from "lucide-react";
|
import { Book, Plus } from "lucide-react";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { EventContentArg } from "@fullcalendar/core";
|
import { EventContentArg } from "@fullcalendar/core";
|
||||||
import EventModal from "./event-modal";
|
import EventModal from "./event-modal";
|
||||||
|
|
@ -25,6 +25,13 @@ import {
|
||||||
PopoverContent,
|
PopoverContent,
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
|
||||||
const wait = () => new Promise((resolve) => setTimeout(resolve, 1000));
|
const wait = () => new Promise((resolve) => setTimeout(resolve, 1000));
|
||||||
interface CalendarViewProps {
|
interface CalendarViewProps {
|
||||||
|
|
@ -103,7 +110,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
|
||||||
const [selectedEventDate, setSelectedEventDate] = useState<Date | null>(null);
|
const [selectedEventDate, setSelectedEventDate] = useState<Date | null>(null);
|
||||||
const roleId = Number(getCookiesDecrypt("urie")) || 0;
|
const roleId = Number(getCookiesDecrypt("urie")) || 0;
|
||||||
const [apiEvents, setApiEvents] = useState<CalendarEvent[]>([]);
|
const [apiEvents, setApiEvents] = useState<CalendarEvent[]>([]);
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [Isloading, setLoading] = useState<boolean>(false);
|
||||||
const [draggableInitialized, setDraggableInitialized] =
|
const [draggableInitialized, setDraggableInitialized] =
|
||||||
useState<boolean>(false);
|
useState<boolean>(false);
|
||||||
const t = useTranslations("CalendarApp");
|
const t = useTranslations("CalendarApp");
|
||||||
|
|
@ -116,6 +123,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
|
||||||
const TODAY = dayjs().format("yyyy-MM-dd");
|
const TODAY = dayjs().format("yyyy-MM-dd");
|
||||||
const INITIAL_YEAR = dayjs().format("YYYY");
|
const INITIAL_YEAR = dayjs().format("YYYY");
|
||||||
const INITIAL_MONTH = dayjs().format("M");
|
const INITIAL_MONTH = dayjs().format("M");
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
const [selectedYear, setSelectedYear] = useState(new Date());
|
const [selectedYear, setSelectedYear] = useState(new Date());
|
||||||
const [selectedMonth, setSelectedMonth] = useState(
|
const [selectedMonth, setSelectedMonth] = useState(
|
||||||
|
|
@ -503,13 +511,44 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getModalContent = (type: "terkirim" | "diterima") => (
|
||||||
|
<div className="overflow-x-auto overflow-y-auto ">
|
||||||
|
{Isloading ? (
|
||||||
|
<p>Loading...</p>
|
||||||
|
) : (
|
||||||
|
<table className="w-full border-collapse border border-gray-300">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-gray-100 border-b">
|
||||||
|
<th className="px-4 py-2 text-left">No</th>
|
||||||
|
<th className="px-4 py-2 text-left">Ticket Number</th>
|
||||||
|
<th className="px-4 py-2 text-left">Date and Time</th>
|
||||||
|
<th className="px-4 py-2 text-left">Title</th>
|
||||||
|
<th className="px-4 py-2 text-left">Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr key={""} className="border-b">
|
||||||
|
<td className="px-4 py-2">{"1"}</td>
|
||||||
|
<td className="px-4 py-2">{"MIA - 001"}</td>
|
||||||
|
<td className="px-4 py-2">{"23/01/2025 13:00"}</td>
|
||||||
|
<td className="px-4 py-2">{"Daily Issue 25 Januari 2025 "}</td>
|
||||||
|
<td className="px-4 py-2">
|
||||||
|
{type === "terkirim" ? "Completed" : "Completed"}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="grid grid-cols-12 gap-6 divide-x divide-border">
|
<div className="grid grid-cols-12 gap-6 divide-x divide-border">
|
||||||
<Card className="col-span-12 lg:col-span-4 2xl:col-span-3 pb-5">
|
<Card className="col-span-12 lg:col-span-4 2xl:col-span-3 pb-5">
|
||||||
<CardContent className="p-0">
|
<CardContent className="p-0">
|
||||||
<CardHeader className="border-none mb-2 pt-5">
|
<CardHeader className="border-none mb-2 pt-5">
|
||||||
{roleId == 11 || roleId == 12 ? (
|
{roleId == 11 || roleId == 2 || roleId == 12 ? (
|
||||||
<Button
|
<Button
|
||||||
onClick={handleDateClick}
|
onClick={handleDateClick}
|
||||||
className="dark:bg-background dark:text-foreground"
|
className="dark:bg-background dark:text-foreground"
|
||||||
|
|
@ -520,6 +559,24 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
|
||||||
) : (
|
) : (
|
||||||
""
|
""
|
||||||
)}
|
)}
|
||||||
|
<div>
|
||||||
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
{roleId == 2 ? (
|
||||||
|
<Button className="dark:bg-background dark:text-foreground ml-2">
|
||||||
|
<Book className="w-4 h-4 me-1" />
|
||||||
|
Hasil Pantauan BAG PA
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="sm:max-w-[425px] md:max-w-[500px] lg:max-w-[1500px] overflow-y-auto max-h-[500px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Hasil Pantauan</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
{getModalContent("terkirim")}
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<div className="px-3">
|
<div className="px-3">
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ import {
|
||||||
DotSquare,
|
DotSquare,
|
||||||
ImageIcon,
|
ImageIcon,
|
||||||
Music,
|
Music,
|
||||||
|
Search,
|
||||||
TrashIcon,
|
TrashIcon,
|
||||||
VideoIcon,
|
VideoIcon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
|
@ -63,6 +64,7 @@ import Image from "next/image";
|
||||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
import WavesurferPlayer from "@wavesurfer/react";
|
import WavesurferPlayer from "@wavesurfer/react";
|
||||||
import WaveSurfer from "wavesurfer.js";
|
import WaveSurfer from "wavesurfer.js";
|
||||||
|
import { InputGroup, InputGroupText } from "@/components/ui/input-group";
|
||||||
|
|
||||||
const taskSchema = z.object({
|
const taskSchema = z.object({
|
||||||
uniqueCode: z.string().min(1, { message: "Judul diperlukan" }),
|
uniqueCode: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
@ -242,6 +244,7 @@ export default function FormTaskDetail() {
|
||||||
const [audioFile, setAudioFile] = useState<File | null>(null);
|
const [audioFile, setAudioFile] = useState<File | null>(null);
|
||||||
const [isRecording, setIsRecording] = useState(false);
|
const [isRecording, setIsRecording] = useState(false);
|
||||||
const [timer, setTimer] = useState<number>(120);
|
const [timer, setTimer] = useState<number>(120);
|
||||||
|
const [search, setSearch] = React.useState<string>("");
|
||||||
|
|
||||||
const [wavesurfer, setWavesurfer] = useState<WaveSurfer>();
|
const [wavesurfer, setWavesurfer] = useState<WaveSurfer>();
|
||||||
const [isPlaying, setIsPlaying] = useState(false);
|
const [isPlaying, setIsPlaying] = useState(false);
|
||||||
|
|
@ -749,6 +752,11 @@ export default function FormTaskDetail() {
|
||||||
|
|
||||||
const handleRemoveFile = (id: number) => {};
|
const handleRemoveFile = (id: number) => {};
|
||||||
|
|
||||||
|
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setSearch(e.target.value); // Perbarui state search
|
||||||
|
// getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
{detail !== undefined ? (
|
{detail !== undefined ? (
|
||||||
|
|
@ -1376,26 +1384,130 @@ export default function FormTaskDetail() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{isTableResult && (
|
{isTableResult && (
|
||||||
<table className="w-full border-collapse border border-gray-300">
|
<div>
|
||||||
<thead>
|
<div className="flex flex-row items-center gap-2 my-2">
|
||||||
<tr className="bg-gray-100 border-b">
|
<div className="mb-3 sm:mb-0 lg-mb-0">
|
||||||
<th className="px-4 py-2 text-left">Judul</th>
|
<InputGroup merged>
|
||||||
<th className="px-4 py-2 text-left">Konten</th>
|
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
|
||||||
<th className="px-4 py-2 text-left">Kategory</th>
|
<Search className=" h-4 w-4 dark:text-white" />
|
||||||
<th className="px-4 py-2 text-left">Diupload Oleh</th>
|
</InputGroupText>
|
||||||
</tr>
|
<Input
|
||||||
</thead>
|
type="text"
|
||||||
<tbody>
|
placeholder="Search Judul..."
|
||||||
{uploadResults.map((item) => (
|
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white w-full"
|
||||||
<tr key={item.id} className="border-b">
|
value={search}
|
||||||
<td className="px-4 py-2">{item.title}</td>
|
onChange={handleSearch}
|
||||||
<td className="px-4 py-2">{item.fileType.name}</td>
|
/>
|
||||||
<td className="px-4 py-2">{item.category.name}</td>
|
</InputGroup>
|
||||||
<td className="px-4 py-2">{item.creatorName}</td>
|
</div>
|
||||||
|
<Dialog>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<Button variant="outline" size="md" color="primary">
|
||||||
|
Filter Polda/Polres
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="sm:max-w-[425px] md:max-w-[500px] lg:max-w-[1500px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>
|
||||||
|
Daftar Wilayah Polda dan Polres
|
||||||
|
</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="grid grid-cols-2 gap-2 max-h-[400px] overflow-y-auto">
|
||||||
|
{listDest.map((polda: any) => (
|
||||||
|
<div key={polda.id} className="border p-2">
|
||||||
|
<Label className="flex items-center">
|
||||||
|
<Checkbox
|
||||||
|
disabled
|
||||||
|
checked={checkedLevels.has(polda.id)}
|
||||||
|
onCheckedChange={() =>
|
||||||
|
handleCheckboxChange(polda.id)
|
||||||
|
}
|
||||||
|
className="mr-3"
|
||||||
|
/>
|
||||||
|
{polda.name}
|
||||||
|
<button
|
||||||
|
onClick={() => toggleExpand(polda.id)}
|
||||||
|
className="ml-2 focus:outline-none"
|
||||||
|
>
|
||||||
|
{expandedPolda[polda.id] ? (
|
||||||
|
<ChevronUp size={16} />
|
||||||
|
) : (
|
||||||
|
<ChevronDown size={16} />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</Label>
|
||||||
|
{expandedPolda[polda.id] && (
|
||||||
|
<div className="ml-6 mt-2">
|
||||||
|
<Label className="block">
|
||||||
|
<Checkbox
|
||||||
|
disabled
|
||||||
|
checked={polda?.subDestination?.every(
|
||||||
|
(polres: any) =>
|
||||||
|
checkedLevels.has(polres.id)
|
||||||
|
)}
|
||||||
|
onCheckedChange={(isChecked) => {
|
||||||
|
const updatedLevels = new Set(
|
||||||
|
checkedLevels
|
||||||
|
);
|
||||||
|
polda?.subDestination?.forEach(
|
||||||
|
(polres: any) => {
|
||||||
|
if (isChecked) {
|
||||||
|
updatedLevels.add(polres.id);
|
||||||
|
} else {
|
||||||
|
updatedLevels.delete(polres.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
setCheckedLevels(updatedLevels);
|
||||||
|
}}
|
||||||
|
className="mr-2"
|
||||||
|
/>
|
||||||
|
Pilih Semua Polres
|
||||||
|
</Label>
|
||||||
|
{polda?.subDestination?.map((polres: any) => (
|
||||||
|
<Label key={polres.id} className="block mt-1">
|
||||||
|
<Checkbox
|
||||||
|
disabled
|
||||||
|
checked={checkedLevels.has(polres.id)}
|
||||||
|
onCheckedChange={() =>
|
||||||
|
handleCheckboxChange(polres.id)
|
||||||
|
}
|
||||||
|
className="mr-2"
|
||||||
|
/>
|
||||||
|
{polres.name}
|
||||||
|
</Label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
<table className="w-full border-collapse border border-gray-300">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-gray-100 border-b">
|
||||||
|
<th className="px-4 py-2 text-left">Judul</th>
|
||||||
|
<th className="px-4 py-2 text-left">Konten</th>
|
||||||
|
<th className="px-4 py-2 text-left">Kategory</th>
|
||||||
|
<th className="px-4 py-2 text-left">Diupload Oleh</th>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
</thead>
|
||||||
</tbody>
|
<tbody>
|
||||||
</table>
|
{uploadResults.map((item) => (
|
||||||
|
<tr key={item.id} className="border-b">
|
||||||
|
<td className="px-4 py-2 text-blue-500">
|
||||||
|
<a href="">{item.title}</a>
|
||||||
|
</td>
|
||||||
|
<td className="px-4 py-2">{item.fileType.name}</td>
|
||||||
|
<td className="px-4 py-2">{item.category.name}</td>
|
||||||
|
<td className="px-4 py-2">{item.creatorName}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
{showInput && (
|
{showInput && (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue