feat:agenda-setting admin, filter detail task

This commit is contained in:
Anang Yusman 2025-02-04 10:57:43 +08:00
parent 071040bdea
commit c9592c0d25
2 changed files with 191 additions and 22 deletions

View File

@ -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">

View File

@ -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,6 +1384,107 @@ export default function FormTaskDetail() {
</div> </div>
</div> </div>
{isTableResult && ( {isTableResult && (
<div>
<div className="flex flex-row items-center gap-2 my-2">
<div className="mb-3 sm:mb-0 lg-mb-0">
<InputGroup merged>
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
<Search className=" h-4 w-4 dark:text-white" />
</InputGroupText>
<Input
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white w-full"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</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"> <table className="w-full border-collapse border border-gray-300">
<thead> <thead>
<tr className="bg-gray-100 border-b"> <tr className="bg-gray-100 border-b">
@ -1388,7 +1497,9 @@ export default function FormTaskDetail() {
<tbody> <tbody>
{uploadResults.map((item) => ( {uploadResults.map((item) => (
<tr key={item.id} className="border-b"> <tr key={item.id} className="border-b">
<td className="px-4 py-2">{item.title}</td> <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.fileType.name}</td>
<td className="px-4 py-2">{item.category.name}</td> <td className="px-4 py-2">{item.category.name}</td>
<td className="px-4 py-2">{item.creatorName}</td> <td className="px-4 py-2">{item.creatorName}</td>
@ -1396,6 +1507,7 @@ export default function FormTaskDetail() {
))} ))}
</tbody> </tbody>
</table> </table>
</div>
)} )}
{showInput && ( {showInput && (
<> <>