feat:agenda setting,content,Spit,task
This commit is contained in:
parent
5a85eaa232
commit
e21fff8309
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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)}
|
||||
/>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -930,7 +930,7 @@ export default function FormImage() {
|
|||
}`}
|
||||
onClick={() => handleArticleIdClick(id)}
|
||||
>
|
||||
{id}
|
||||
{"Narasi " + (index + 1)}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue