feat:agenda setting,content,Spit,task

This commit is contained in:
Anang Yusman 2025-02-05 17:02:13 +08:00
parent 5a85eaa232
commit e21fff8309
7 changed files with 184 additions and 28 deletions

View File

@ -34,6 +34,9 @@ const FormSchema = z.object({
email: z.string({
required_error: "Required",
}),
position: z.string({
required_error: "Required",
}),
region: z.string({
required_error: "Required",
}),
@ -147,7 +150,28 @@ export default function AddExpertForm() {
</FormItem>
)}
/>
<FormField
control={form.control}
name="position"
render={({ field }) => (
<FormItem>
<FormLabel>Posisi</FormLabel>
<Select onValueChange={field.onChange} value={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Pilih Region" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="koor-kurator">Koor Kurator</SelectItem>
<SelectItem value="kurator">Kurator</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="region"

View File

@ -10,7 +10,15 @@ import { Label } from "@/components/ui/label";
import ExternalDraggingevent from "./dragging-events";
import { Calendar } from "@/components/ui/calendar";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Book, CheckSquare2, CheckSquare2Icon, Plus } from "lucide-react";
import {
Book,
CheckCheck,
CheckSquare2,
CheckSquare2Icon,
Plus,
Timer,
TimerIcon,
} from "lucide-react";
import { Checkbox } from "@/components/ui/checkbox";
import { EventContentArg } from "@fullcalendar/core";
import EventModal from "./event-modal";
@ -46,6 +54,7 @@ export type CalendarEvent = {
end: Date;
createBy: string;
createdByName: string;
isPublish: boolean | null;
allDay: boolean;
extendedProps: {
calendar: string;
@ -94,6 +103,7 @@ interface ListItemProps {
item: any;
text: string;
createdBy: string;
isPublish: boolean | null;
bgColor: string;
}
@ -175,12 +185,15 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
end: new Date(event.endDate),
allDay: true,
extendedProps: {
isPublish: event.isPublish,
calendar: event.agendaType,
description: event.description,
createdByName: event.createdByName,
},
}));
console.log("Dataaa event : ", events);
setCalendarEvents(events);
}
};
@ -238,6 +251,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
title: item.title,
createBy: "Mabes Polri - Approver",
createdByName: item.createdByName,
isPublish: item.isPublish,
start: new Date(item.startDate),
end: new Date(item.endDate),
allDay: true, // Sesuaikan jika memang ada event sepanjang hari
@ -334,14 +348,13 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
const renderEventContent = (eventInfo: any) => {
const { title } = eventInfo.event;
const { isPublish } = eventInfo.event.extendedProps;
const { createdByName } = eventInfo.event.extendedProps;
const { createdByName, isPublish } = eventInfo.event.extendedProps;
return (
<>
<div className="flex flex-row">
{" "}
{isPublish && <CheckSquare2 />}
{isPublish === true ? <CheckCheck size={15} /> : <Timer size={15} />}
<p className="ml-1">{title}</p>
</div>
@ -415,6 +428,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
end: new Date(item.endDate),
createBy: "Mabes Polri - Approver", // Sesuaikan dengan data yang sebenarnya jika ada
createdByName: item.createdByName,
isPublish: item.isPublish,
allDay: true,
extendedProps: {
calendar: item.agendaType,
@ -437,6 +451,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
item,
text,
createdBy,
isPublish,
bgColor,
}) => (
<div
@ -444,7 +459,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
onClick={() => handleClickListItem(item)}
>
<div className="flex flex-row items-center">
<CheckSquare2Icon />
{isPublish ? <CheckCheck size={15} /> : <Timer size={15} />}
<p className="ml-1">{text}</p>
</div>
<p className="ml-1 text-xs text-start mt-2">Created By: {createdBy}</p>
@ -475,6 +490,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
item={event}
text={event.title}
createdBy={event.createdByName}
isPublish={event.isPublish}
bgColor={getEventColor(event.agendaType)}
/>
))}
@ -504,6 +520,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
item={event}
text={event.title}
createdBy={event.createdByName}
isPublish={event.isPublish}
bgColor={getEventColor(event.agendaType)}
/>
))}

View File

@ -26,6 +26,7 @@ import {
} from "@/components/ui/table";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import {
ChevronDown,
ChevronLeft,
ChevronRight,
Eye,
@ -52,6 +53,8 @@ import { useRouter, useSearchParams } from "next/navigation";
import TablePagination from "@/components/table/table-pagination";
import columns from "./columns";
import { listTask } from "@/service/task";
import { Label } from "@/components/ui/label";
import { format } from "date-fns";
const TaskTable = () => {
const router = useRouter();
@ -70,6 +73,10 @@ const TaskTable = () => {
pageIndex: 0,
pageSize: 10,
});
const [statusFilter, setStatusFilter] = React.useState<any[]>([]);
const [dateFilter, setDateFilter] = React.useState("");
const [endDate, setEndDate] = React.useState("");
const [filterByCode, setFilterByCode] = React.useState<string>("");
const [page, setPage] = React.useState(1);
const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10);
@ -106,14 +113,19 @@ const TaskTable = () => {
React.useEffect(() => {
fetchData();
}, [page, limit, isSpecificAttention, search]);
}, [page, limit, isSpecificAttention, search, dateFilter, filterByCode]);
async function fetchData() {
const formattedStartDate = dateFilter
? format(new Date(dateFilter), "yyyy-MM-dd")
: "";
try {
const res = await listTask(
search,
page - 1,
search,
limit,
filterByCode,
formattedStartDate,
isSpecificAttention ? "atensi-khusus" : "tugas-harian"
);
const data = res?.data?.data;
@ -137,6 +149,21 @@ const TaskTable = () => {
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
function handleStatusCheckboxChange(value: any) {
setStatusFilter((prev: any) =>
prev.includes(value)
? prev.filter((status: any) => status !== value)
: [...prev, value]
);
}
const handleSearchFilterByCode = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
console.log("code :", value);
setFilterByCode(value);
fetchData();
};
return (
<div className="w-full overflow-x-auto">
<div className="mx-5 mb-3">
@ -191,17 +218,81 @@ const TaskTable = () => {
/>
</InputGroup>
</div>
<div className="flex-none">
<Input
placeholder="Filter Status..."
value={
(table.getColumn("status")?.getFilterValue() as string) ?? ""
}
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
table.getColumn("status")?.setFilterValue(event.target.value)
}
className="max-w-sm "
/>
<div className="flex flex-row items-center gap-2">
<div className="flex flex-row items-center gap-3">
<div className="flex items-center py-4">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="ml-auto" size="md">
Filter <ChevronDown />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
className="w-64 h-[200px] overflow-y-auto"
>
<div className="flex flex-row justify-between my-1 mx-1">
<p>Filter</p>
</div>
<div className="mx-2 my-1">
<Label>Tanggal Awal</Label>
<Input
type="date"
value={dateFilter}
onChange={(e) => setDateFilter(e.target.value)}
className="max-w-sm"
/>
</div>
<div className="mx-2 my-1">
<Label>Code</Label>
<Input
placeholder="Filter Status..."
value={filterByCode}
onChange={handleSearchFilterByCode}
className="max-w-sm"
/>
</div>
<Label className="ml-2 mt-2">Status</Label>
<div className="flex items-center px-4 py-1">
<input
type="checkbox"
id="status-2"
className="mr-2"
checked={statusFilter.includes(1)}
onChange={() => handleStatusCheckboxChange(1)}
/>
<label htmlFor="status-2" className="text-sm">
Selesai
</label>
</div>
<div className="flex items-center px-4 py-1">
<input
type="checkbox"
id="status-2"
className="mr-2"
checked={statusFilter.includes(2)}
onChange={() => handleStatusCheckboxChange(2)}
/>
<label htmlFor="status-2" className="text-sm">
Aktif
</label>
</div>
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
<div className="flex-none">
<Input
placeholder="Filter Status..."
value={
(table.getColumn("status")?.getFilterValue() as string) ?? ""
}
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
table.getColumn("status")?.setFilterValue(event.target.value)
}
className="max-w-sm "
/>
</div>
</div>
</div>
<Table className="overflow-hidden mt-3">

View File

@ -930,7 +930,7 @@ export default function FormImage() {
}`}
onClick={() => handleArticleIdClick(id)}
>
{id}
{"Narasi " + (index + 1)}
</p>
))}
</div>

View File

@ -653,7 +653,7 @@ export default function FormConvertSPIT() {
}`}
onClick={() => handleArticleIdClick(id)}
>
{id}
{"Narasi " + (index + 1)}
</button>
))}
</div>
@ -737,6 +737,9 @@ export default function FormConvertSPIT() {
</div>
</div>
</div>
<div className="mt-3">
<Label className="text-xl">Penempatan file</Label>
</div>
{files?.map((file, index) => (
<div
key={file.contentId}

View File

@ -172,6 +172,7 @@ interface UploadResult {
title: string;
description: string;
createdAt: string;
creatorGroupLevelName: string;
category: { name: string };
fileType: { name: string };
uploadStatus: { name: string };
@ -327,13 +328,24 @@ export default function FormTaskDetail() {
fetchPoldaPolres();
}, []);
const fetchAllData = async () => {
try {
const response = await getMediaUpload(id, userLevelId);
setUploadResults(response?.data?.data || []);
} catch (error) {
console.error("Error fetching all data:", error);
}
};
const fetchFilteredData = async (selectedLevels: any[]) => {
try {
const levels =
selectedLevels.length === 0 ? userLevelId : selectedLevels.join(",");
if (selectedLevels.length === 0) {
fetchAllData(); // Jika tidak ada filter, panggil semua data
return;
}
const levels = selectedLevels.join(",");
const response = await getMediaUpload(id, levels);
setUploadResults(response?.data?.data || []);
} catch (error) {
console.error("Error fetching filtered data:", error);
@ -462,7 +474,6 @@ export default function FormTaskDetail() {
console.log("Checked Levels:", Array.from(updatedLevels));
// Fetch data dengan filter userLevelId
fetchFilteredData(Array.from(updatedLevels));
return updatedLevels;
@ -1413,7 +1424,10 @@ export default function FormTaskDetail() {
type="button"
color="primary"
variant={"default"}
onClick={() => setIsTableResult(!isTableResult)}
onClick={() => {
setIsTableResult(!isTableResult);
if (!isTableResult) fetchAllData(); // Panggil API saat tombol diklik
}}
>
Hasil Upload {Number(userId)}
</Button>
@ -1525,6 +1539,7 @@ export default function FormTaskDetail() {
<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">Kreator</th>
<th className="px-4 py-2 text-left">Diupload Oleh</th>
</tr>
</thead>
@ -1536,6 +1551,9 @@ export default function FormTaskDetail() {
</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.creatorGroupLevelName}
</td>
<td className="px-4 py-2">{item.creatorName}</td>
</tr>
))}

View File

@ -12,13 +12,16 @@ import {
// }
export async function listTask(
title: string = "",
page: any,
title: string = "",
size: any,
code: any,
createdAt: any,
taskType: string
) {
const url = `assignment/list?enablePage=1&size=${size}&page=${page}&title=${title}&taskType=${taskType}`;
return httpGetInterceptor(url);
return httpGetInterceptor(
`assignment/list?enablePage=1&size=${size}&page=${page}&title=${title}&taskType=${taskType}&uniqueCode=${code}&createdAt=${createdAt}`
);
}
// export async function createTask(data: any) {