merge main

This commit is contained in:
Rama Priyanto 2024-12-23 14:57:32 +07:00
commit 1068b9e6a3
218 changed files with 13223 additions and 3272 deletions

View File

@ -1,30 +0,0 @@
import SiteBreadcrumb from "@/components/site-breadcrumb";
import { Card, CardContent } from "@/components/ui/card";
import { UploadIcon } from "lucide-react";
import PressReleaseTable from "../schedule/press-conference/components/presscon-table";
import { Button } from "@/components/ui/button";
import ContestTable from "./table-contest/contest-table";
const ContestPage = async () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<Card className="py-4 px-3">
<div className="flex flex-row justify-between items-center">
<div className="flex-1 text-xl font-medium text-default-900">
Table Lomba
</div>
</div>
</Card>
<Card>
<CardContent className="p-0">
<ContestTable />
</CardContent>
</Card>
</div>
</div>
);
};
export default ContestPage;

View File

@ -1,348 +0,0 @@
"use client";
import * as React from "react";
import {
ColumnDef,
ColumnFiltersState,
PaginationState,
SortingState,
VisibilityState,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import { Button } from "@/components/ui/button";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import {
Badge,
ChevronLeft,
ChevronRight,
Eye,
MoreVertical,
Search,
SquarePen,
Trash2,
TrendingDown,
TrendingUp,
} from "lucide-react";
import { cn } from "@/lib/utils";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
export type CompanyData = {
no: number;
hastagCode: string;
theme: string;
duration: string;
targetOutput: string;
targetParticipantTopLevel: string;
isPublishForAll: string;
};
import { data } from "./data";
import { Input } from "@/components/ui/input";
import { InputGroup, InputGroupText } from "@/components/ui/input-group";
import { listTask } from "@/service/task";
import { listContest } from "@/service/contest/contest";
export const columns: ColumnDef<CompanyData>[] = [
{
accessorKey: "no",
header: "No",
cell: ({ row }) => (
<div className="flex items-center gap-5">
<div className="flex-1 text-start">
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
{row.getValue("no")}
</h4>
</div>
</div>
),
},
{
accessorKey: "hastagCode",
header: "Kode",
cell: ({ row }) => (
<div className="flex items-center gap-5">
<div className="flex-1 text-start">
<h4
className="text-sm font-bold
text-default-600 whitespace-nowrap mb-1"
>
{row.getValue("hastagCode")}
</h4>
</div>
</div>
),
},
{
accessorKey: "theme",
header: "Judul",
cell: ({ row }) => (
<div className="flex items-center gap-5">
<div className="flex-1 text-start">
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
{row.getValue("theme")}
</h4>
</div>
</div>
),
},
{
accessorKey: "duration",
header: "Durasi ",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("duration")}</span>
),
},
{
accessorKey: "targetOutput",
header: "Target Output ",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("targetOutput")}</span>
),
},
{
accessorKey: "targetParticipantTopLevel",
header: "Tag ",
cell: ({ row }) => (
<span className="whitespace-nowrap">
{row.getValue("targetParticipantTopLevel")}
</span>
),
},
{
accessorKey: "isPublishForAll",
header: "Status",
cell: ({ row }) => {
return (
<span className="whitespace-nowrap text-blue-600">
{row.getValue("isPublishForAll")}
</span>
);
},
},
{
id: "actions",
accessorKey: "action",
header: "Actions",
enableHiding: false,
cell: ({ row }) => {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
size="icon"
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
>
<span className="sr-only">Open menu</span>
<MoreVertical className="h-4 w-4 text-default-800" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
},
},
];
const ContestTable = () => {
const [contestTable, setContestTable] = React.useState<CompanyData[]>([]);
const [sorting, setSorting] = React.useState<SortingState>([]);
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
);
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({});
const [rowSelection, setRowSelection] = React.useState({});
const [pagination, setPagination] = React.useState<PaginationState>({
pageIndex: 0,
pageSize: 2,
});
const [page, setPage] = React.useState(1);
const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10);
const table = useReactTable({
data: contestTable,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility,
onRowSelectionChange: setRowSelection,
onPaginationChange: setPagination,
state: {
sorting,
columnFilters,
columnVisibility,
rowSelection,
pagination,
},
});
React.useEffect(() => {
initState();
}, [page, limit]);
async function initState() {
try {
const res = await listContest(limit, page);
console.log("res", res?.data?.data);
const data = res.data.data.content.map((item: any, index: number) => ({
no: (page - 1) * limit + index + 1,
hastagCode: item.hastagCode,
theme: item.theme,
targetOutput: item.targetOutput,
targetParticipantTopLevel: item.targetParticipantTopLevel,
duration: item.duration,
isDone: item.isDone,
}));
setContestTable(data);
setTotalPage(res.data.totalPages);
} catch (error) {
console.error("Error fetching tasks:", error);
}
}
return (
<div className="w-full overflow-x-auto">
<div className="flex justify-between items-center py-4 px-5">
<div>
<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"
/>
</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>
</div>
<Table className="overflow-hidden">
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id} className="bg-default-200">
{headerGroup.headers.map((header) => (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
className="h-[75px]"
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={columns.length} className="h-24 text-center">
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
<div className="flex items-center justify-center py-4 gap-2 flex-none">
<Button
variant="outline"
size="icon"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
className="w-8 h-8"
>
<ChevronLeft className="w-4 h-4" />
</Button>
{table.getPageOptions().map((page, pageIndex) => (
<Button
key={`basic-data-table-${pageIndex}`}
onClick={() => table.setPageIndex(pageIndex)}
size="icon"
className="w-8 h-8"
variant={
table.getState().pagination.pageIndex === pageIndex
? "default"
: "outline"
}
>
{page + 1}
</Button>
))}
<Button
variant="outline"
size="icon"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
className="w-8 h-8"
>
<ChevronRight className="w-4 h-4" />
</Button>
</div>
</div>
);
};
export default ContestTable;

View File

@ -1,74 +0,0 @@
export const data = [
{
title: "Ops Mantap Praja & Pilkada 2024",
code: "#NEWLOMBA",
duration: "2023-08-31 07:00:00 - 2023-09-01 07:00:00",
targetOutput: "Foto",
targetParticipant: "Polda, mabes",
status: "Terkirim",
},
{
title: "Seputar Prestasi",
code: "#NEWLOMBA",
duration: "2023-08-31 07:00:00 - 2023-09-01 07:00:00",
targetOutput: "Foto",
targetParticipant: "Polda, mabes",
status: "Terkirim",
},
{
title: "Ops Mantap Praja & Pilkada 2024",
code: "#NEWLOMBA",
duration: "2023-08-31 07:00:00 - 2023-09-01 07:00:00",
targetOutput: "Foto",
targetParticipant: "Polda, mabes",
status: "Terkirim",
},
{
title: "Ops Mantap Praja & Pilkada 2024",
code: "#NEWLOMBA",
duration: "2023-08-31 07:00:00 - 2023-09-01 07:00:00",
targetOutput: "Foto",
targetParticipant: "Polda, mabes",
status: "Terkirim",
},
{
title: "Seputar Prestasi",
code: "#NEWLOMBA",
duration: "2023-08-31 07:00:00 - 2023-09-01 07:00:00",
targetOutput: "Foto",
targetParticipant: "Polda, mabes",
status: "Terkirim",
},
{
title: "Seputar Prestasi",
code: "#NEWLOMBA",
duration: "2023-08-31 07:00:00 - 2023-09-01 07:00:00",
targetOutput: "Foto",
targetParticipant: "Polda, mabes",
status: "Terkirim",
},
{
title: "Seputar Prestasi",
code: "#NEWLOMBA",
duration: "2023-08-31 07:00:00 - 2023-09-01 07:00:00",
targetOutput: "Foto",
targetParticipant: "Polda, mabes",
status: "Terkirim",
},
{
title: "Seputar Prestasi",
code: "#NEWLOMBA",
duration: "2023-08-31 07:00:00 - 2023-09-01 07:00:00",
targetOutput: "Foto",
targetParticipant: "Polda, mabes",
status: "Terkirim",
},
{
title: "Seputar Prestasi",
code: "#NEWLOMBA",
duration: "2023-08-31 07:00:00 - 2023-09-01 07:00:00",
targetOutput: "Foto",
targetParticipant: "Polda, mabes",
status: "Terkirim",
},
];

View File

@ -12,7 +12,7 @@ import { Calendar } from "@/components/ui/calendar";
import { Card, CardContent, CardHeader } from "@/components/ui/card";
import { Plus } from "lucide-react";
import { Checkbox } from "@/components/ui/checkbox";
import { CalendarEvent, CalendarCategory } from "./data";
import { CalendarCategory } from "./data";
import { EventContentArg } from "@fullcalendar/core";
import EventModal from "./event-modal";
import { useTranslations } from "next-intl";
@ -26,15 +26,49 @@ interface CalendarViewProps {
const INITIAL_YEAR = dayjs().format("YYYY");
const INITIAL_MONTH = dayjs().format("M");
export interface CalendarEvent {
id: string;
title: string;
start: Date;
end: Date;
allDay: boolean;
extendedProps: {
calendar: string;
description?: string;
};
}
export interface AgendaSettingsAPIResponse {
id: number;
title: string;
description: string;
agendaType: string;
startDate: string; // API mengembalikan tanggal dalam bentuk string
endDate: string;
isActive: boolean;
createdAt: string;
updatedAt: string;
createdById: number | null;
createdByName: string | null;
}
interface APIResponse {
error: boolean;
message: any;
data: AgendaSettingsAPIResponse[] | null; // `data` bisa berupa array atau null
}
const CalendarView = ({ events, categories }: CalendarViewProps) => {
const [selectedCategory, setSelectedCategory] = useState<string[] | null>(
null
);
const [selectedEventDate, setSelectedEventDate] = useState<Date | null>(null);
const [selectedEvent, setSelectedEvent] = useState<CalendarEvent | null>(
null
);
// const [selectedEvent, setSelectedEvent] = useState<CalendarEvent | null>(
// null
// );
const [apiEvents, setApiEvents] = useState<CalendarEvent[]>([]);
const [loading, setLoading] = useState<boolean>(false);
const [draggableInitialized, setDraggableInitialized] =
useState<boolean>(false);
const t = useTranslations("CalendarApp");
@ -65,6 +99,73 @@ const CalendarView = ({ events, categories }: CalendarViewProps) => {
setSelectedCategory(categories?.map((c) => c.value));
}, [events, categories]);
useEffect(() => {
console.log("Fetched events from API:", apiEvents);
}, [apiEvents]);
const filteredEvents = apiEvents?.filter((event) =>
selectedCategory?.includes(event.extendedProps.calendar)
);
const displayedEvents =
filteredEvents?.length > 0 ? filteredEvents : apiEvents;
useEffect(() => {
console.log("Filtered events based on category:", displayedEvents);
}, [filteredEvents, apiEvents]);
useEffect(() => {
setSelectedCategory(categories?.map((c) => c.value));
}, [categories]);
useEffect(() => {
console.log("Selected categories:", selectedCategory);
}, [selectedCategory]);
useEffect(() => {
const fetchAgendaEvents = async () => {
setLoading(true);
try {
const selectedMonth = new Date(); // Replace with your logic for selected month
const year = selectedMonth.getFullYear().toString();
const month = (selectedMonth.getMonth() + 1).toString();
const typeFilter = ""; // Replace with your type filter logic if needed
const response: APIResponse = await getAgendaSettingsList(
year,
month,
typeFilter
);
if (response.data && Array.isArray(response.data)) {
// Transform API data to match CalendarEvent type
const eventsFromAPI: CalendarEvent[] = response.data.map((item) => ({
id: item.id.toString(),
title: item.title,
start: new Date(item.startDate),
end: new Date(item.endDate),
allDay: true, // Sesuaikan jika memang ada event sepanjang hari
extendedProps: {
calendar: item.agendaType,
description: item.description,
},
}));
setApiEvents(eventsFromAPI);
} else {
console.warn("No events found in API response.");
setApiEvents([]);
}
} catch (error) {
console.error("Failed to fetch agenda settings:", error);
setApiEvents([]);
} finally {
setLoading(false);
}
};
fetchAgendaEvents();
}, []);
useEffect(() => {
const draggableEl = document.getElementById("external-events");
@ -97,23 +198,24 @@ const CalendarView = ({ events, categories }: CalendarViewProps) => {
draggableEl?.removeEventListener("mousedown", initDraggable);
};
}, [dragEvents]);
// event click
const handleEventClick = (arg: any) => {
setSelectedEventDate(null);
setSheetOpen(true);
setSelectedEvent(arg);
setApiEvents(arg);
wait().then(() => (document.body.style.pointerEvents = "auto"));
};
// handle close modal
const handleCloseModal = () => {
setSheetOpen(false);
setSelectedEvent(null);
setApiEvents([]);
setSelectedEventDate(null);
};
const handleDateClick = (arg: any) => {
setSheetOpen(true);
setSelectedEventDate(arg);
setSelectedEvent(null);
setApiEvents([]);
wait().then(() => (document.body.style.pointerEvents = "auto"));
};
@ -126,12 +228,12 @@ const CalendarView = ({ events, categories }: CalendarViewProps) => {
};
const handleClassName = (arg: EventContentArg) => {
if (arg.event.extendedProps.calendar === "national") {
return "destructive";
} else if (arg.event.extendedProps.calendar === "polda") {
if (arg.event.extendedProps.calendar === "mabes") {
return "primary";
} else if (arg.event.extendedProps.calendar === "polres") {
} else if (arg.event.extendedProps.calendar === "polda") {
return "success";
} else if (arg.event.extendedProps.calendar === "polres") {
return "destructive";
} else if (arg.event.extendedProps.calendar === "international") {
return "info";
} else {
@ -139,10 +241,6 @@ const CalendarView = ({ events, categories }: CalendarViewProps) => {
}
};
const filteredEvents = events?.filter((event) =>
selectedCategory?.includes(event.extendedProps.calendar)
);
return (
<>
<div className="grid grid-cols-12 gap-6 divide-x divide-border">
@ -222,7 +320,7 @@ const CalendarView = ({ events, categories }: CalendarViewProps) => {
center: "title",
right: "dayGridMonth,timeGridWeek,timeGridDay,listWeek",
}}
events={filteredEvents}
events={displayedEvents} // Use apiEvents here
editable={true}
rerenderDelay={10}
eventDurationEditable={false}
@ -243,7 +341,7 @@ const CalendarView = ({ events, categories }: CalendarViewProps) => {
open={sheetOpen}
onClose={handleCloseModal}
categories={categories}
event={selectedEvent}
event={apiEvents}
selectedDate={selectedEventDate}
/>
</>

View File

@ -1,4 +1,4 @@
"use client";
// "use client";
import React, { useState, useEffect } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
@ -30,9 +30,18 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Textarea } from "@/components/ui/textarea";
import { error, loading } from "@/lib/swal";
import Cookies from "js-cookie";
import Swal from "sweetalert2";
import withReactContent from "sweetalert2-react-content";
import { useRouter } from "next/navigation";
import { postSchedule } from "@/service/schedule/schedule";
import { saveAgendaSettings } from "@/service/agenda-setting/agenda-setting";
const schema = z.object({
title: z.string().min(3, { message: "Required" }),
description: z.string().min(3, { message: "Required" }),
});
const EventModal = ({
@ -57,6 +66,8 @@ const EventModal = ({
// delete modal state
const [deleteModalOpen, setDeleteModalOpen] = useState<boolean>(false);
const [eventIdToDelete, setEventIdToDelete] = useState<string | null>(null);
const MySwal = withReactContent(Swal);
const router = useRouter();
const {
register,
@ -70,20 +81,45 @@ const EventModal = ({
mode: "all",
});
const onSubmit = (data: any) => {
startTransition(() => {
if (!event) {
data.start = startDate;
data.end = endDate;
data.allDay = false;
data.extendedProps = {
calendar: calendarProps,
};
}
if (event) {
}
const save = async (data: any) => {
// loading();
const reqData = {
title: data.title,
description: data.description || "",
agendaType: calendarProps,
startDate: format(startDate, "yyyy-MM-dd"),
endDate: format(endDate, "yyyy-MM-dd"),
};
console.log("Submitted Data:", reqData);
const response = await saveAgendaSettings(reqData);
if (response.error) {
error(response.message);
return false;
}
Cookies.set("AgendaSetting", response.data.data.id, {
expires: 1,
});
// Optional: Use Swal for success feedback
MySwal.fire({
title: "Sukses",
text: "Data berhasil disimpan.",
icon: "success",
confirmButtonColor: "#3085d6",
confirmButtonText: "OK",
}).then(() => {
router.push("/contributor/agenda-setting");
});
};
const onSubmit = (data: any) => {
save(data);
};
useEffect(() => {
if (selectedDate) {
setStartDate(selectedDate.date);
@ -93,13 +129,10 @@ const EventModal = ({
setStartDate(event?.event?.start);
setEndDate(event?.event?.end);
const eventCalendar = event?.event?.extendedProps?.calendar;
if (eventCalendar) {
setCalendarProps(eventCalendar);
} else {
setCalendarProps(categories[0].value);
}
setCalendarProps(eventCalendar || categories[0].value);
}
setValue("title", event?.event?.title || "");
setValue("description", event?.event?.description || "");
}, [event, selectedDate, open, categories, setValue]);
const onDeleteEventAction = async () => {
@ -125,14 +158,15 @@ const EventModal = ({
<DialogContent onPointerDownOutside={onClose}>
<DialogHeader>
<DialogTitle>
{event ? "Edit Event" : "Create Event"} {event?.title}
{event ? "Edit Agenda Setting" : "Create Agenda Setting"}{" "}
{event?.title}
</DialogTitle>
</DialogHeader>
<div className="mt-6 h-full">
<form className="h-full" onSubmit={handleSubmit(onSubmit)}>
<div className="space-y-4 pb-5 ">
<div className="space-y-1.5">
<Label htmlFor="title">Event Name</Label>
<Label htmlFor="title">Judul Agenda</Label>
<Input
id="title"
type="text"
@ -222,7 +256,7 @@ const EventModal = ({
</div>
<div className="space-y-1.5">
<Label htmlFor="calendarProps">Label </Label>
<Label htmlFor="calendarProps">Jenis Agenda </Label>
<Controller
name="calendarProps"
control={control}
@ -248,6 +282,21 @@ const EventModal = ({
)}
/>
</div>
<div className="space-y-1.5">
<Label htmlFor="description">Isi Agenda Setting</Label>
<Textarea
id="description"
placeholder="Enter Event Name"
{...register("description")}
/>
{errors?.description?.message && (
<div className="text-destructive text-sm">
{typeof errors?.description?.message === "string"
? errors?.description?.message
: JSON.stringify(errors?.description?.message)}
</div>
)}
</div>
</div>
<div className="flex flex-wrap gap-2 mt-10">
@ -258,9 +307,9 @@ const EventModal = ({
{event ? "Updating..." : "Adding..."}
</>
) : event ? (
"Update Event"
"Update Agenda Setting"
) : (
"Add Event"
"Simpan Agenda Setting"
)}
</Button>
{event && (

View File

@ -55,6 +55,7 @@ const BlogTable = () => {
const [page, setPage] = React.useState(1);
const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10);
const [search, setSearch] = React.useState<string>("");
const table = useReactTable({
data: dataTable,
@ -86,11 +87,11 @@ const BlogTable = () => {
React.useEffect(() => {
fetchData();
}, [page, limit]);
}, [page, limit, search]);
async function fetchData() {
try {
const res = await paginationBlog(limit, page - 1, "");
const res = await paginationBlog(limit, page - 1, search);
const data = res.data?.data;
const contentData = data?.content;
contentData.forEach((item: any, index: number) => {
@ -107,6 +108,11 @@ const BlogTable = () => {
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="flex justify-between items-center px-5">
@ -119,6 +125,8 @@ const BlogTable = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>

View File

@ -12,6 +12,7 @@ import {
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { format } from "date-fns";
import { Link } from "@/components/navigation";
const columns: ColumnDef<any>[] = [
{
@ -95,18 +96,22 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<Link href={`/contributor/blog/detail/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
{/*
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuItem> */}
</DropdownMenuContent>
</DropdownMenu>
);

View File

@ -0,0 +1,18 @@
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormImage from "@/components/form/content/image-form";
import FormBlog from "@/components/form/blog/blog-form";
const BlogCreatePage = async () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormBlog />
</div>
</div>
);
};
export default BlogCreatePage;

View File

@ -0,0 +1,15 @@
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormBlogDetail from "@/components/form/blog/blog--detail-form";
const BlogDetailPage = async () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormBlogDetail />
</div>
</div>
);
};
export default BlogDetailPage;

View File

@ -3,6 +3,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import BlogTable from "./components/blog-table";
import { Plus } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Link } from "@/components/navigation";
const BlogPage = async () => {
return (
@ -17,10 +18,12 @@ const BlogPage = async () => {
Table Indeks
</div>
<div className="flex-none">
<Button fullWidth size="md">
<Plus className="w-6 h-6 me-1.5" />
Add Index
</Button>
<Link href={"/contributor/blog/create"}>
<Button fullWidth color="primary">
<Plus className="w-6 h-6 me-1.5" />
Add Index
</Button>
</Link>
</div>
</div>
</CardTitle>

View File

@ -139,7 +139,7 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<a href="/en/task/detail/[id]">
<a href="/contributor/task/detail/[id]">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View

View File

@ -121,7 +121,7 @@ const TableAudio = () => {
React.useEffect(() => {
fetchData();
}, [page, limit]);
}, [page, limit, search]);
async function fetchData() {
try {
@ -140,7 +140,7 @@ const TableAudio = () => {
filterBySource,
startDateString,
endDateString,
""
search
);
const data = res.data?.data;
const contentData = data?.content;
@ -157,6 +157,10 @@ const TableAudio = () => {
console.error("Error fetching tasks:", error);
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
@ -170,6 +174,8 @@ const TableAudio = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>

View File

@ -5,7 +5,6 @@ import { Link, UploadIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Icon } from "@iconify/react/dist/iconify.js";
import TableAudio from "./components/table-audio";
import TableVideo from "../audio-visual/components/table-video";
const ReactTableAudioPage = () => {
return (

View File

@ -139,7 +139,7 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<a href="/en/task/detail/[id]">
<a href="/contributor/task/detail/[id]">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View

View File

@ -73,7 +73,7 @@ const TableImage = () => {
const [page, setPage] = React.useState(1);
const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10);
const [search, setSearch] = React.useState<string>("");
const [search, setSearch] = React.useState("");
const userId = getCookiesDecrypt("uie");
const userLevelId = getCookiesDecrypt("ulie");
@ -117,7 +117,7 @@ const TableImage = () => {
React.useEffect(() => {
fetchData();
}, [page, limit]);
}, [page, limit, search]);
async function fetchData() {
try {
@ -136,7 +136,7 @@ const TableImage = () => {
filterBySource,
startDateString,
endDateString,
""
search
);
const data = res.data?.data;
const contentData = data?.content;
@ -154,6 +154,11 @@ const TableImage = () => {
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="flex justify-between items-center px-5">
@ -166,6 +171,8 @@ const TableImage = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>

View File

@ -6,7 +6,6 @@ import { UploadIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Icon } from "@iconify/react/dist/iconify.js";
import { Link } from "@/components/navigation";
import TicketingTable from "../../ticketing/components/table";
const ReactTableImagePage = () => {
return (
@ -58,7 +57,7 @@ const ReactTableImagePage = () => {
Konten Foto
</div>
<div className="flex-none">
<Link href={"/content/image/create"}>
<Link href={"/contributor/content/image/create"}>
<Button color="primary" className="text-white">
<UploadIcon />
Unggah Foto

View File

@ -88,7 +88,7 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<a href="/en/task/detail/[id]">
<a href="/contributor/task/detail/[id]">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View

View File

@ -121,12 +121,12 @@ const TableTeks = () => {
React.useEffect(() => {
fetchData();
}, [page, limit]);
}, [page, limit, search]);
async function fetchData() {
try {
const isForSelf = Number(roleId) == 4;
const res = await listNulisAI(limit, page - 1, "");
const res = await listNulisAI(limit, page - 1, search);
const data = res.data?.data;
const contentData = data?.content;
contentData.forEach((item: any, index: number) => {
@ -143,6 +143,11 @@ const TableTeks = () => {
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="flex justify-between items-center px-5">
@ -155,6 +160,8 @@ const TableTeks = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>

View File

@ -177,7 +177,7 @@ const columns: ColumnDef<CompanyData>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<a href="/en/task/detail/[id]">
<a href="/contributor/task/detail/[id]">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View

View File

@ -139,7 +139,7 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<a href="/en/task/detail/[id]">
<a href="/contributor/task/detail/[id]">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View

View File

@ -117,7 +117,7 @@ const TableTeks = () => {
React.useEffect(() => {
fetchData();
}, [page, limit]);
}, [page, limit, search]);
async function fetchData() {
try {
@ -136,7 +136,7 @@ const TableTeks = () => {
filterBySource,
startDateString,
endDateString,
""
search
);
const data = res.data?.data;
const contentData = data?.content;
@ -154,6 +154,11 @@ const TableTeks = () => {
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="flex justify-between items-center px-5">
@ -166,6 +171,8 @@ const TableTeks = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>

View File

@ -139,7 +139,7 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<a href="/en/task/detail/[id]">
<a href="/contributor/task/detail/[id]">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View

View File

@ -117,7 +117,7 @@ const TableImage = () => {
React.useEffect(() => {
fetchData();
}, [page, limit]);
}, [page, limit, search]);
async function fetchData() {
try {
@ -136,7 +136,7 @@ const TableImage = () => {
filterBySource,
startDateString,
endDateString,
""
search
);
const data = res.data?.data;
const contentData = data?.content;
@ -154,6 +154,11 @@ const TableImage = () => {
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="flex justify-between items-center px-5">
@ -166,6 +171,8 @@ const TableImage = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>

View File

@ -58,7 +58,7 @@ const ReactTableVideoPage = () => {
Konten Video
</div>
<div className="flex-none">
<Link href={"/content/audio-visual/create"}>
<Link href={"/contributor/content/audio-visual/create"}>
<Button color="primary" className="text-white">
<UploadIcon />
Unggah Video

View File

@ -11,6 +11,8 @@ import {
} from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { format } from "date-fns";
import { Link } from "@/components/navigation";
const columns: ColumnDef<any>[] = [
{
@ -42,9 +44,18 @@ const columns: ColumnDef<any>[] = [
{
accessorKey: "createdAt",
header: "Tanggal Unggah ",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("createdAt")}</span>
),
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-";
return <span className="whitespace-nowrap">{formattedDate}</span>;
},
},
{
accessorKey: "isActive",
@ -81,15 +92,18 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Link
href={`/contributor/planning/mediahub/publish/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
Publish
</DropdownMenuItem>
</Link>
<DropdownMenuItem
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
// onClick={() => deletePlan(row.id)}
>
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>

View File

@ -52,6 +52,7 @@ import { useRouter, useSearchParams } from "next/navigation";
import TablePagination from "@/components/table/table-pagination";
import columns from "./columns";
import { getPlanningSentPagination } from "@/service/planning/planning";
import search from "@/app/[locale]/(protected)/app/chat/components/search";
const MediahubTable = () => {
const router = useRouter();
@ -73,6 +74,7 @@ const MediahubTable = () => {
const [page, setPage] = React.useState(1);
const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10);
const [search, setSearch] = React.useState("");
const table = useReactTable({
data: dataTable,
@ -104,11 +106,11 @@ const MediahubTable = () => {
React.useEffect(() => {
fetchData();
}, [page, limit]);
}, [page, limit, search]);
async function fetchData() {
try {
const res = await getPlanningSentPagination(limit, page - 1, 1, "");
const res = await getPlanningSentPagination(limit, page - 1, 1, search);
const data = res.data?.data;
const contentData = data?.content;
contentData.forEach((item: any, index: number) => {
@ -125,6 +127,11 @@ const MediahubTable = () => {
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="flex justify-between items-center px-5">
@ -137,6 +144,8 @@ const MediahubTable = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>

View File

@ -4,7 +4,6 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { UploadIcon } from "lucide-react";
import TaskTable from "../../task/components/task-table";
import MediahubTable from "./components/mediahub-table";
import TicketingTable from "../../ticketing/components/table";
const MediahubPage = async () => {
return (

View File

@ -0,0 +1,17 @@
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import PublishMediahub from "@/components/form/planning/mediahub-publish";
const MediahubPublishPage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<PublishMediahub />
</div>
</div>
);
};
export default MediahubPublishPage;

View File

@ -11,6 +11,8 @@ import {
} from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { format } from "date-fns";
import { Link } from "@/components/navigation";
const columns: ColumnDef<any>[] = [
{
@ -42,9 +44,18 @@ const columns: ColumnDef<any>[] = [
{
accessorKey: "createdAt",
header: "Tanggal Unggah ",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("createdAt")}</span>
),
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-";
return <span className="whitespace-nowrap">{formattedDate}</span>;
},
},
{
accessorKey: "isActive",
@ -81,14 +92,15 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
<Link
href={`/contributor/planning/medsos-mediahub/publish/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
Publish
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete

View File

@ -73,6 +73,7 @@ const MedsosTable = () => {
const [page, setPage] = React.useState(1);
const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10);
const [search, setSearch] = React.useState("");
const table = useReactTable({
data: dataTable,
@ -104,11 +105,11 @@ const MedsosTable = () => {
React.useEffect(() => {
fetchData();
}, [page, limit]);
}, [page, limit, search]);
async function fetchData() {
try {
const res = await getPlanningSentPagination(limit, page - 1, 2, "");
const res = await getPlanningSentPagination(limit, page - 1, 2, search);
const data = res.data?.data;
const contentData = data?.content;
contentData.forEach((item: any, index: number) => {
@ -125,6 +126,11 @@ const MedsosTable = () => {
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="flex justify-between items-center px-5">
@ -137,6 +143,8 @@ const MedsosTable = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
onChange={handleSearch}
value={search}
/>
</InputGroup>
</div>

View File

@ -1,7 +1,6 @@
import SiteBreadcrumb from "@/components/site-breadcrumb";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import MedsosTable from "./components/medsos-table";
import TicketingTable from "../../ticketing/components/table";
const MedsosMediahubPage = async () => {
return (

View File

@ -0,0 +1,16 @@
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import PublishMedsos from "@/components/form/planning/medsos-publish";
const MedsosPublishPage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<PublishMedsos />
</div>
</div>
);
};
export default MedsosPublishPage;

View File

@ -11,6 +11,7 @@ import {
} from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Link } from "@/components/navigation";
const columns: ColumnDef<any>[] = [
{
@ -54,11 +55,17 @@ const columns: ColumnDef<any>[] = [
),
},
{
accessorKey: "startTime",
accessorKey: "time",
header: "Time",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("startTime")}</span>
),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { startTime, endTime } = row.original;
return (
<span className="whitespace-nowrap">
{startTime || "N/A"} - {endTime || "N/A"}
</span>
);
},
},
{
accessorKey: "address",
@ -99,11 +106,17 @@ const columns: ColumnDef<any>[] = [
},
},
{
accessorKey: "speakerName",
accessorKey: "speaker",
header: "Disampaikan oleh",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("speakerName")}</span>
),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { speakerTitle, speakerName } = row.original;
return (
<span className="whitespace-nowrap">
{speakerTitle || ""} {speakerName || ""}
</span>
);
},
},
{
accessorKey: "uploaderName",
@ -131,14 +144,22 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
<Link
href={`/contributor/schedule/event/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link
href={`/contributor/schedule/event/update/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete

View File

@ -50,6 +50,7 @@ const EventTable = () => {
const [page, setPage] = React.useState(1);
const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10);
const [search, setSearch] = React.useState<string>("");
const table = useReactTable({
data: dataTable,
@ -81,11 +82,11 @@ const EventTable = () => {
React.useEffect(() => {
fetchData();
}, [page, limit]);
}, [page, limit, search]);
async function fetchData() {
try {
const res = await paginationSchedule(limit, page - 1, 2, "");
const res = await paginationSchedule(limit, page - 1, 2, search);
const data = res.data?.data;
const contentData = data?.content;
contentData.forEach((item: any, index: number) => {
@ -102,6 +103,11 @@ const EventTable = () => {
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="flex justify-between items-center px-5">
@ -114,6 +120,8 @@ const EventTable = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>

View File

@ -0,0 +1,22 @@
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormPressConference from "@/components/form/schedule/press-conference-form";
import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form";
import { useParams } from "next/navigation";
import { id } from "date-fns/locale";
import FormEventDetail from "@/components/form/schedule/event-detail-form";
const EventDetailPage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormEventDetail />
</div>
</div>
);
};
export default EventDetailPage;

View File

@ -5,7 +5,6 @@ import { UploadIcon } from "lucide-react";
import PressConferenceTable from "../press-conference/components/presscon-table";
import EventTable from "./components/event-table";
import { Link } from "@/components/navigation";
import TicketingTable from "../../ticketing/components/table";
const EventPage = async () => {
return (
@ -20,7 +19,7 @@ const EventPage = async () => {
Jadwal Event
</div>
<div className="flex-none">
<Link href={"/schedule/event/create"}>
<Link href={"/contributor/schedule/event/create"}>
<Button color="primary" className="text-white">
<UploadIcon />
Buat Jadwal

View File

@ -0,0 +1,23 @@
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormPressConference from "@/components/form/schedule/press-conference-form";
import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form";
import { useParams } from "next/navigation";
import { id } from "date-fns/locale";
import FormUpdatePressConference from "@/components/form/schedule/press-conference-update-form";
import FormEventUpdate from "@/components/form/schedule/event-update-form";
const EventUpdatePage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormEventUpdate />
</div>
</div>
);
};
export default EventUpdatePage;

View File

@ -11,6 +11,7 @@ import {
} from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Link } from "@/components/navigation";
const columns: ColumnDef<any>[] = [
{
@ -54,11 +55,17 @@ const columns: ColumnDef<any>[] = [
),
},
{
accessorKey: "startTime",
accessorKey: "time",
header: "Time",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("startTime")}</span>
),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { startTime, endTime } = row.original;
return (
<span className="whitespace-nowrap">
{startTime || "N/A"} - {endTime || "N/A"}
</span>
);
},
},
{
accessorKey: "address",
@ -99,11 +106,17 @@ const columns: ColumnDef<any>[] = [
},
},
{
accessorKey: "speakerName",
accessorKey: "speaker",
header: "Disampaikan oleh",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("speakerName")}</span>
),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { speakerTitle, speakerName } = row.original;
return (
<span className="whitespace-nowrap">
{speakerTitle || ""} {speakerName || ""}
</span>
);
},
},
{
accessorKey: "uploaderName",
@ -131,14 +144,22 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
<Link
href={`/contributor/schedule/press-conference/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
Detail
</DropdownMenuItem>
</Link>
<Link
href={`/contributor/schedule/press-conference/update/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete

View File

@ -63,6 +63,7 @@ const PressConferenceTable = () => {
const [page, setPage] = React.useState(1);
const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10);
const [search, setSearch] = React.useState<string>("");
const table = useReactTable({
data: dataTable,
@ -94,11 +95,11 @@ const PressConferenceTable = () => {
React.useEffect(() => {
fetchData();
}, [page, limit]);
}, [page, limit, search]);
async function fetchData() {
try {
const res = await paginationSchedule(limit, page - 1, 1, "");
const res = await paginationSchedule(limit, page - 1, 1, search);
const data = res.data?.data;
const contentData = data?.content;
contentData.forEach((item: any, index: number) => {
@ -115,6 +116,11 @@ const PressConferenceTable = () => {
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="flex justify-between items-center px-5">
@ -127,6 +133,8 @@ const PressConferenceTable = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>

View File

@ -3,7 +3,7 @@ import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormPressConference from "@/components/form/schedule/press-conference-form";
const PressConCreatePage = async () => {
const PressConCreatePage = () => {
return (
<div>
<SiteBreadcrumb />

View File

@ -0,0 +1,21 @@
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormPressConference from "@/components/form/schedule/press-conference-form";
import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form";
import { useParams } from "next/navigation";
import { id } from "date-fns/locale";
const PressConDetailPage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormDetailPressConference />
</div>
</div>
);
};
export default PressConDetailPage;

View File

@ -4,7 +4,6 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import PressConferenceTable from "./components/presscon-table";
import { UploadIcon } from "lucide-react";
import { Link } from "@/components/navigation";
import TicketingTable from "../../ticketing/components/table";
const PressConferencePage = async () => {
return (
@ -19,7 +18,7 @@ const PressConferencePage = async () => {
Jadwal Konferensi Pers
</div>
<div className="flex-none">
<Link href={"/schedule/press-conference/create"}>
<Link href={"/contributor/schedule/press-conference/create"}>
<Button color="primary" className="text-white">
<UploadIcon />
Buat Jadwal

View File

@ -0,0 +1,22 @@
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormPressConference from "@/components/form/schedule/press-conference-form";
import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form";
import { useParams } from "next/navigation";
import { id } from "date-fns/locale";
import FormUpdatePressConference from "@/components/form/schedule/press-conference-update-form";
const PressConUpdatePage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormUpdatePressConference />
</div>
</div>
);
};
export default PressConUpdatePage;

View File

@ -11,6 +11,7 @@ import {
} from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Link } from "@/components/navigation";
const columns: ColumnDef<any>[] = [
{
@ -54,11 +55,17 @@ const columns: ColumnDef<any>[] = [
),
},
{
accessorKey: "startTime",
accessorKey: "time",
header: "Time",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("startTime")}</span>
),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { startTime, endTime } = row.original;
return (
<span className="whitespace-nowrap">
{startTime || "N/A"} - {endTime || "N/A"}
</span>
);
},
},
{
accessorKey: "address",
@ -99,11 +106,17 @@ const columns: ColumnDef<any>[] = [
},
},
{
accessorKey: "speakerName",
accessorKey: "speaker",
header: "Disampaikan oleh",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("speakerName")}</span>
),
cell: ({ row }: { row: { original: any } }) => {
console.log("Row Original Data:", row.original);
const { speakerTitle, speakerName } = row.original;
return (
<span className="whitespace-nowrap">
{speakerTitle || ""} {speakerName || ""}
</span>
);
},
},
{
accessorKey: "uploaderName",
@ -131,14 +144,22 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
<Link
href={`/contributor/schedule/press-release/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<Link
href={`/contributor/schedule/press-release/update/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete

View File

@ -64,6 +64,7 @@ const PressReleaseTable = () => {
const [page, setPage] = React.useState(1);
const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10);
const [search, setSearch] = React.useState<string>("");
const table = useReactTable({
data: dataTable,
@ -95,11 +96,11 @@ const PressReleaseTable = () => {
React.useEffect(() => {
fetchData();
}, [page, limit]);
}, [page, limit, search]);
async function fetchData() {
try {
const res = await paginationSchedule(limit, page - 1, 3, "");
const res = await paginationSchedule(limit, page - 1, 3, search);
const data = res.data?.data;
const contentData = data?.content;
contentData.forEach((item: any, index: number) => {
@ -116,9 +117,14 @@ const PressReleaseTable = () => {
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="flex justify-between items-center px-5">
<div className="flex justify-between items-center px-5 mt-3">
<div>
<InputGroup merged>
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
@ -128,6 +134,8 @@ const PressReleaseTable = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>

View File

@ -4,7 +4,7 @@ import FormTask from "@/components/form/task/task-form";
import FormPressConference from "@/components/form/schedule/press-conference-form";
import FormPressRelease from "@/components/form/schedule/pers-release-form";
const PressReleaseCreatePage = async () => {
const PressReleaseCreatePage = () => {
return (
<div>
<SiteBreadcrumb />

View File

@ -0,0 +1,17 @@
"use client";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form";
import FormDetailPressRillis from "@/components/form/schedule/pers-release--detail-form";
const PressRilisDetailPage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormDetailPressRillis />
</div>
</div>
);
};
export default PressRilisDetailPage;

View File

@ -3,7 +3,6 @@ import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { UploadIcon } from "lucide-react";
import { Link } from "@/components/navigation";
import TicketingTable from "../../ticketing/components/table";
import PressReleaseTable from "./components/pressrilis-table";
const PressReleasePage = async () => {
@ -19,7 +18,7 @@ const PressReleasePage = async () => {
Jadwal Pers Rilis
</div>
<div className="flex-none">
<Link href={"/schedule/press-release/create"}>
<Link href={"/contributor/schedule/press-release/create"}>
<Button color="primary" className="text-white">
<UploadIcon />
Buat Jadwal

View File

@ -0,0 +1,23 @@
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormPressConference from "@/components/form/schedule/press-conference-form";
import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form";
import { useParams } from "next/navigation";
import { id } from "date-fns/locale";
import FormUpdatePressConference from "@/components/form/schedule/press-conference-update-form";
import FormUpdatePressRelease from "@/components/form/schedule/pers-release--update-form";
const PressRilisUpdatePage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormUpdatePressRelease />
</div>
</div>
);
};
export default PressRilisUpdatePage;

View File

@ -12,6 +12,7 @@ import {
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { format } from "date-fns";
import { Link } from "@/components/navigation";
const columns: ColumnDef<any>[] = [
{
@ -111,10 +112,12 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<Link href={`/contributor/task/detail/${row.original.id}`}>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit

View File

@ -73,7 +73,8 @@ const TaskTable = () => {
const [page, setPage] = React.useState(1);
const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10);
const [activeTab, setActiveTab] = React.useState("atensi-khusus");
const [isSpecificAttention, setIsSpecificAttention] = React.useState(true);
const [search, setSearch] = React.useState<string>("");
const table = useReactTable({
data: dataTable,
@ -105,11 +106,16 @@ const TaskTable = () => {
React.useEffect(() => {
fetchData();
}, [page, limit, activeTab]);
}, [page, limit, isSpecificAttention, search]);
async function fetchData() {
try {
const res = await listTask("", page - 1, limit, activeTab);
const res = await listTask(
search,
page - 1,
limit,
isSpecificAttention ? "atensi-khusus" : "tugas-harian"
);
const data = res.data?.data;
const contentData = data?.content;
contentData.forEach((item: any, index: number) => {
@ -126,27 +132,47 @@ const TaskTable = () => {
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="mx-5 mb-3">
<div className="">
<div className="row">
<Button
onClick={() => setActiveTab("atensi-khusus")}
className={`col-md-6 text-center rounded-none ${
activeTab == "atensi-khusus" ? "text-blue-600" : "text-muted"
}`}
>
Atensi Khusus
</Button>
<Button
onClick={() => setActiveTab("tugas-harian")}
className={`col text-center rounded-none ${
activeTab == "tugas-harian" ? "text-blue-600" : "text-muted"
}`}
>
Tugas Harian
</Button>
<div className="flex justify-between mb-6">
<label className="inline-flex text-md cursor-pointer">
<input
type="checkbox"
onChange={() => setIsSpecificAttention(!isSpecificAttention)}
hidden
/>
<span
className={` ${
isSpecificAttention
? "bg-default-900 text-white"
: "dark:text-default-700 border-2"
}
px-[18px] py-1 transition duration-100 rounded`}
>
Atensi Khusus
</span>
<span
className={`
${
!isSpecificAttention
? "bg-default-900 text-white"
: " dark:text-default-700 border-2"
}
px-[18px] py-1 transition duration-100 rounded
`}
>
Tugas Harian
</span>
</label>
</div>
</div>
</div>
</div>
@ -160,6 +186,8 @@ const TaskTable = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>

View File

@ -2,7 +2,7 @@ import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
const TaskCreatePage = async () => {
const TaskCreatePage = () => {
return (
<div>
<SiteBreadcrumb />

View File

@ -1,13 +1,14 @@
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormTaskDetail from "@/components/form/task/task-detail-form";
const TaskDetailPage = async () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormTask />
<FormTaskDetail />
</div>
</div>
);

View File

@ -7,7 +7,6 @@ import SiteBreadcrumb from "@/components/site-breadcrumb";
import { Link } from "@/components/navigation";
import { checkAuthorization, checkLoginSession } from "@/lib/utils";
import React, { useEffect } from "react";
import TicketingTable from "../ticketing/components/table";
const TaskPage = () => {
useEffect(() => {
@ -31,7 +30,7 @@ const TaskPage = () => {
Table Penugasan
</div>
<div className="flex-none">
<Link href={"/task/create"}>
<Link href={"/contributor/task/create"}>
<Button color="primary" className="text-white">
<UploadIcon />
Buat Penugasan

View File

@ -6,16 +6,18 @@ import { useTranslations } from "next-intl";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Button } from "@/components/ui/button";
import { UploadIcon } from "lucide-react";
import RecentActivity from "./routine-task/recent-activity";
import CompanyTable from "./routine-task/routine-task-table";
import TaskTable from "../task/components/task-table";
import PressConferenceTable from "../schedule/press-release/components/pressrilis-table";
import BlogTable from "../blog/components/blog-table";
import Cookies from "js-cookie";
import { useEffect } from "react";
import { getCookiesDecrypt } from "@/lib/utils";
import DashboardVisualization from "@/components/visualization/dashboard-viz";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import TaskTable from "../contributor/task/components/task-table";
import PressConferenceTable from "../contributor/schedule/press-release/components/pressrilis-table";
import BlogTable from "../contributor/blog/components/blog-table";
import ContentTable from "./routine-task/components/content-table";
import RecentActivity from "./routine-task/components/recent-activity";
import { Link } from "@/components/navigation";
const DashboardPage = () => {
const t = useTranslations("AnalyticsDashboard");
@ -107,7 +109,7 @@ const DashboardPage = () => {
<DashboardDropdown />
</CardHeader>
<CardContent className="p-0">
<CompanyTable />
<ContentTable />
</CardContent>
</Card>
</div>
@ -123,14 +125,16 @@ const DashboardPage = () => {
Table Penugasan
</div>
<div>
<Button color="primary" className="text-white">
<UploadIcon />
Buat Penugasan
</Button>
<Link href={"/contributor/task/create"}>
<Button color="primary" className="text-white">
<UploadIcon />
Buat Penugasan
</Button>
</Link>
</div>
</div>
</Card>
<CardContent className="p-0">
<CardContent className="p-0 mt-3">
<TaskTable />
</CardContent>
</Card>
@ -141,7 +145,7 @@ const DashboardPage = () => {
<div className="grid grid-cols-12 gap-5">
<div className="lg:col-span-12 col-span-12">
<Card>
<CardContent className="p-0">
<CardContent className="p-0 ">
<PressConferenceTable />
</CardContent>
</Card>
@ -158,14 +162,16 @@ const DashboardPage = () => {
Table Indeks
</div>
<div>
<Button color="primary" className="text-white">
<UploadIcon />
Tambah Indeks
</Button>
<Link href={"/contributor/blog/create"}>
<Button color="primary" className="text-white">
<UploadIcon />
Tambah Indeks
</Button>
</Link>
</div>
</div>
</Card>
<CardContent className="p-0">
<CardContent className="p-0 mt-3">
<BlogTable />
</CardContent>
</Card>

View File

@ -0,0 +1,174 @@
import * as React from "react";
import { ColumnDef } from "@tanstack/react-table";
import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react";
import { cn } from "@/lib/utils";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
DropdownMenuItem,
} from "@/components/ui/dropdown-menu";
import { Button } from "@/components/ui/button";
import { format } from "date-fns";
const columns: ColumnDef<any>[] = [
{
accessorKey: "no",
header: "No",
cell: ({ row }) => (
<div className="flex items-center gap-5">
<div className="flex-1 text-start">
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
{row.getValue("no")}
</h4>
</div>
</div>
),
},
{
accessorKey: "title",
header: "Title",
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
const title: string = row.getValue("title");
return (
<span className="">
{title.length > 50 ? `${title.slice(0, 10)}...` : title}
</span>
);
},
},
{
accessorKey: "createdAt",
header: "Upload Date",
cell: ({ row }) => {
const createdAt = row.getValue("createdAt") as
| string
| number
| undefined;
const formattedDate =
createdAt && !isNaN(new Date(createdAt).getTime())
? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss")
: "-";
return <span className="whitespace-nowrap">{formattedDate}</span>;
},
},
{
accessorKey: "fileTypeName",
header: "Type Content",
cell: ({ row }: { row: { getValue: (key: string) => string } }) => {
const title: string = row.getValue("fileTypeName");
return (
<span className="whitespace-nowrap">
{title.length > 50 ? `${title.slice(0, 30)}...` : title}
</span>
);
},
},
// {
// accessorKey: "creatorGroup",
// header: "Creator Group",
// cell: ({ row }) => (
// <span className="whitespace-nowrap">{row.getValue("creatorGroup")}</span>
// ),
// },
// {
// accessorKey: "creatorName",
// header: "Sumber",
// cell: ({ row }) => (
// <span className="whitespace-nowrap">{row.getValue("creatorName")}</span>
// ),
// },
// {
// accessorKey: "publishedOn",
// header: "Published",
// cell: ({ row }) => {
// const isPublish = row.original.isPublish;
// const isPublishOnPolda = row.original.isPublishOnPolda;
// let displayText = "-";
// if (isPublish && !isPublishOnPolda) {
// displayText = "Mabes";
// } else if (isPublish && isPublishOnPolda) {
// displayText = "Mabes & Polda";
// } else if (!isPublish && isPublishOnPolda) {
// displayText = "Polda";
// }
// return (
// <div className="text-center whitespace-nowrap" title={displayText}>
// {displayText}
// </div>
// );
// },
// },
{
accessorKey: "statusName",
header: "Status",
cell: ({ row }) => {
// Mendapatkan nilai statusName
const statusName = row.getValue<string>("statusName");
// Mapping warna berdasarkan statusName
const colorMapping: Record<string, string> = {
"Menunggu Review": "text-orange-500 border-orange-500",
Diterima: "text-green-500 border-green-500",
"Minta Update": "text-blue-500 border-blue-500",
Ditolak: "text-red-500 border-red-500",
};
// Mendapatkan kelas warna dari mapping, default ke abu-abu jika tidak ditemukan
const buttonClass =
colorMapping[statusName] || "text-gray-500 border-gray-500";
return (
<div>
<Button
size="sm"
variant="outline"
className={`btn btn-sm pill-btn ml-1 ${buttonClass}`}
>
{statusName || "Tidak Diketahui"}
</Button>
</div>
);
},
},
{
id: "actions",
accessorKey: "action",
header: "Actions",
enableHiding: false,
cell: ({ row }) => {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
size="icon"
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
>
<span className="sr-only">Open menu</span>
<MoreVertical className="h-4 w-4 text-default-800" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<a href="/en/task/detail/[id]">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</a>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
},
},
];
export default columns;

View File

@ -0,0 +1,278 @@
"use client";
import * as React from "react";
import {
ColumnDef,
ColumnFiltersState,
PaginationState,
SortingState,
VisibilityState,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import { Button } from "@/components/ui/button";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import {
ChevronLeft,
ChevronRight,
Eye,
MoreVertical,
Search,
SquarePen,
Trash2,
TrendingDown,
TrendingUp,
} from "lucide-react";
import { cn, getCookiesDecrypt } from "@/lib/utils";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";
import { InputGroup, InputGroupText } from "@/components/ui/input-group";
import { paginationBlog } from "@/service/blog/blog";
import { ticketingPagination } from "@/service/ticketing/ticketing";
import { Badge } from "@/components/ui/badge";
import { useRouter, useSearchParams } from "next/navigation";
import TablePagination from "@/components/table/table-pagination";
import columns from "./columns";
import { listDataAll, listDataImage } from "@/service/content/content";
import { Icon } from "@iconify/react/dist/iconify.js";
import {
Select,
SelectContent,
SelectGroup,
SelectItem,
SelectLabel,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
type StatusFilter = string[];
const ContentTable = () => {
const router = useRouter();
const searchParams = useSearchParams();
const [dataTable, setDataTable] = React.useState<any[]>([]);
const [totalData, setTotalData] = React.useState<number>(1);
const [sorting, setSorting] = React.useState<SortingState>([]);
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
);
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({});
const [rowSelection, setRowSelection] = React.useState({});
const [pagination, setPagination] = React.useState<PaginationState>({
pageIndex: 0,
pageSize: 10,
});
const [page, setPage] = React.useState(1);
const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10);
const userId = getCookiesDecrypt("uie");
const userLevelId = getCookiesDecrypt("ulie");
const [categories, setCategories] = React.useState<string[]>();
const [categoryFilter, setCategoryFilter] = React.useState<string[]>([]);
const [statusFilter, setStatusFilter] = React.useState<StatusFilter>([]);
const [startDateString, setStartDateString] = React.useState<string>("");
const [endDateString, setEndDateString] = React.useState<string>("");
const [filterByCreator, setFilterByCreator] = React.useState<string>("");
const [fileTypeFilter, setFileTypeFilter] = React.useState<string[]>([]);
const [filterBySource, setFilterBySource] = React.useState<string>("");
const [search, setSearch] = React.useState("");
const roleId = getCookiesDecrypt("urie");
const table = useReactTable({
data: dataTable,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility,
onRowSelectionChange: setRowSelection,
onPaginationChange: setPagination,
state: {
sorting,
columnFilters,
columnVisibility,
rowSelection,
pagination,
},
});
React.useEffect(() => {
const pageFromUrl = searchParams?.get("page");
if (pageFromUrl) {
setPage(Number(pageFromUrl));
}
}, [searchParams]);
React.useEffect(() => {
fetchData();
}, [page, limit, fileTypeFilter, statusFilter, search]);
async function fetchData() {
try {
const isForSelf = Number(roleId) === 4;
const res = await listDataAll(
isForSelf,
!isForSelf,
page - 1,
limit,
fileTypeFilter.sort().join(","),
categoryFilter.sort().join(","),
statusFilter.sort().join(","),
statusFilter.sort().join(",").includes("1") ? userLevelId : "",
filterByCreator,
filterBySource,
startDateString,
endDateString,
search
);
const data = res.data?.data;
const contentData = data?.content;
contentData.forEach((item: any, index: number) => {
item.no = (page - 1) * limit + index + 1;
});
console.log("contentData : ", contentData);
setDataTable(contentData);
setTotalData(data?.totalElements);
setTotalPage(data?.totalPages);
} catch (error) {
console.error("Error fetching tasks:", error);
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="flex justify-between items-center px-5">
<div>
<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"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>
<div className="flex flex-row items-center gap-3">
{/* <Select
onValueChange={(value) => {
setStatusFilter([value]);
}}
>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select a Filter Status" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Status</SelectLabel>
<SelectItem value="1">Menunggu Review</SelectItem>
<SelectItem value="2">Diterima</SelectItem>
<SelectItem value="3">Minta Update</SelectItem>
<SelectItem value="4">Ditolak</SelectItem>
</SelectGroup>
</SelectContent>
</Select> */}
<Select
onValueChange={(value) => {
setFileTypeFilter([value]);
}}
>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select a Filter" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Filter</SelectLabel>
<SelectItem value="1">Image</SelectItem>
<SelectItem value="2">Video</SelectItem>
<SelectItem value="3">Teks</SelectItem>
<SelectItem value="4">Audio</SelectItem>
</SelectGroup>
</SelectContent>
</Select>
</div>
</div>
<Table className="overflow-hidden mt-3">
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id} className="bg-default-200">
{headerGroup.headers.map((header) => (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
className="h-[75px]"
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={columns.length} className="h-24 text-center">
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
<TablePagination
table={table}
totalData={totalData}
totalPage={totalPage}
/>
</div>
);
};
export default ContentTable;

View File

@ -0,0 +1,136 @@
"use client";
import { getCookiesDecrypt } from "@/lib/utils";
import { listDataAll } from "@/service/content/content";
import {
ColumnFiltersState,
PaginationState,
SortingState,
VisibilityState,
} from "@tanstack/react-table";
import { DockIcon, ImageIcon, MicIcon, YoutubeIcon } from "lucide-react";
import { useRouter, useSearchParams } from "next/navigation";
import React from "react";
import search from "../../../app/chat/components/search";
type StatusFilter = string[];
interface Counts {
images: number;
audiovisual: number;
text: number;
audio: number;
}
const RecentActivity: React.FC = () => {
const router = useRouter();
const searchParams = useSearchParams();
const [dataTable, setDataTable] = React.useState<any[]>([]);
const [totalData, setTotalData] = React.useState<number>(1);
const [sorting, setSorting] = React.useState<SortingState>([]);
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
);
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({});
const [rowSelection, setRowSelection] = React.useState({});
const [pagination, setPagination] = React.useState<PaginationState>({
pageIndex: 0,
pageSize: 10,
});
const [page, setPage] = React.useState(1);
const [totalPage, setTotalPage] = React.useState(1);
const [limit, setLimit] = React.useState(10);
const [search, setSearch] = React.useState<string>("");
const userId = getCookiesDecrypt("uie");
const userLevelId = getCookiesDecrypt("ulie");
const [categories, setCategories] = React.useState<string[]>();
const [categoryFilter, setCategoryFilter] = React.useState<string[]>([]);
const [statusFilter, setStatusFilter] = React.useState<StatusFilter>([]);
const [startDateString, setStartDateString] = React.useState<string>("");
const [endDateString, setEndDateString] = React.useState<string>("");
const [filterByCreator, setFilterByCreator] = React.useState<string>("");
const [fileTypeFilter, setFileTypeFilter] = React.useState<string[]>([]);
const [filterBySource, setFilterBySource] = React.useState<string>("");
const [counts, setCounts] = React.useState<Counts>({
images: 0,
audiovisual: 0,
text: 0,
audio: 0,
});
const roleId = getCookiesDecrypt("urie");
React.useEffect(() => {
const pageFromUrl = searchParams?.get("page");
if (pageFromUrl) {
setPage(Number(pageFromUrl));
}
}, [searchParams]);
React.useEffect(() => {
fetchData();
}, [page, limit]);
async function fetchData() {
try {
const isForSelf = Number(roleId) === 4;
const res = await listDataAll(
isForSelf,
!isForSelf,
page - 1,
limit,
search,
fileTypeFilter.sort().join(","),
categoryFilter.sort().join(","),
statusFilter.sort().join(","),
statusFilter.sort().join(",").includes("1") ? userLevelId : "",
filterByCreator,
filterBySource,
startDateString,
endDateString
);
const data = res.data?.data;
const { content } = data || [];
// Calculate counts for each typeId
const newCounts: Counts = {
images: content.filter((item: any) => item.typeId === 1).length,
audiovisual: content.filter((item: any) => item.typeId === 2).length,
text: content.filter((item: any) => item.typeId === 3).length,
audio: content.filter((item: any) => item.typeId === 4).length,
};
setDataTable(content);
setCounts(newCounts);
} catch (error) {
console.error("Error fetching tasks:", error);
}
}
return (
<div className="flex flex-col gap-5">
<div className="flex flex-row items-center gap-3">
<ImageIcon size={40} className="text-blue-700" />
<p className="text-xl">{counts.images} FOTO</p>
</div>
<div className="flex flex-row items-center gap-3">
<YoutubeIcon size={40} className="text-blue-700" />
<p className="text-xl">{counts.audiovisual} AUDIO VISUAL</p>
</div>
<div className="flex flex-row items-center gap-3">
<DockIcon size={40} className="text-blue-700" />
<p className="text-xl">{counts.text} TEXT</p>
</div>
<div className="flex flex-row items-center gap-3">
<MicIcon size={40} className="text-blue-700" />
<p className="text-xl">{counts.audio} AUDIO</p>
</div>
</div>
);
};
export default RecentActivity;

View File

@ -1,36 +0,0 @@
"use client";
import {
DockIcon,
ImageIcon,
MicIcon,
PaperclipIcon,
TextIcon,
VideoIcon,
YoutubeIcon,
} from "lucide-react";
const RecentActivity = () => {
return (
<div className="flex flex-col gap-5">
<div className="flex flex-row items-center gap-3">
<ImageIcon size={40} className="text-blue-700" />
<p className="text-xl">0 FOTO</p>
</div>
<div className="flex flex-row items-center gap-3">
<YoutubeIcon size={40} className="text-blue-700" />
<p className="text-xl">0 AUDIO VISUAL</p>
</div>
<div className="flex flex-row items-center gap-3">
<DockIcon size={40} className="text-blue-700" />
<p className="text-xl">0 TEXT</p>
</div>
<div className="flex flex-row items-center gap-3">
<MicIcon size={40} className="text-blue-700" />
<p className="text-xl">0 AUDIO</p>
</div>
</div>
);
};
export default RecentActivity;

View File

@ -1,272 +0,0 @@
"use client";
import * as React from "react";
import {
ColumnDef,
ColumnFiltersState,
PaginationState,
SortingState,
VisibilityState,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import { Button } from "@/components/ui/button";
import { data } from "./data";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import {
Badge,
ChevronLeft,
ChevronRight,
Eye,
MoreVertical,
SquarePen,
Trash2,
TrendingDown,
TrendingUp,
} from "lucide-react";
import { cn } from "@/lib/utils";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
export type CompanyData = {
company: string;
category: string;
revenue: string;
sales: number;
status: string;
up: boolean;
};
export const columns: ColumnDef<CompanyData>[] = [
{
accessorKey: "company",
header: "Judul",
cell: ({ row }) => (
<div className="flex items-center gap-5">
<div className="flex-none">
<div className="w-8 h-8">
<Avatar>
<AvatarImage src={row.getValue("company")}></AvatarImage>
<AvatarFallback>SC</AvatarFallback>
</Avatar>
</div>
</div>
<div className="flex-1 text-start">
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
Biffco Enterprises Ltd.
</h4>
<div className="text-xs font-normal text-default-600 ">
Biffco@example.com
</div>
</div>
</div>
),
},
{
accessorKey: "category",
header: "Tanggal Unggah",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("category")}</span>
),
},
{
accessorKey: "sales",
header: "Tipe Konten",
cell: ({ row }) => (
<div className="flex items-center gap-4">
<span>{row.getValue("sales")}</span>
{row?.original.up ? (
<TrendingUp className="text-success w-4 h-4" />
) : (
<TrendingDown className="text-destructive w-4 h-4" />
)}
</div>
),
},
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<CompanyData["status"], string> = {
paid: "bg-success/20 text-success",
due: "bg-warning/20 text-warning",
canceled: "bg-destructive/20 text-destructive",
};
const status = row.getValue<CompanyData["status"]>("status");
return (
<Badge className={cn("rounded-full px-5", statusColors[status])}>
{status}
</Badge>
);
},
},
{
id: "actions",
accessorKey: "action",
header: "Actions",
enableHiding: false,
cell: ({ row }) => {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
size="icon"
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
>
<span className="sr-only">Open menu</span>
<MoreVertical className="h-4 w-4 text-default-800" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit
</DropdownMenuItem>
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
<Trash2 className="w-4 h-4 me-1.5" />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
},
},
];
const CompanyTable = () => {
const [sorting, setSorting] = React.useState<SortingState>([]);
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
);
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({});
const [rowSelection, setRowSelection] = React.useState({});
const [pagination, setPagination] = React.useState<PaginationState>({
pageIndex: 0,
pageSize: 6,
});
const table = useReactTable({
data,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility,
onRowSelectionChange: setRowSelection,
onPaginationChange: setPagination,
state: {
sorting,
columnFilters,
columnVisibility,
rowSelection,
pagination,
},
});
return (
<div className="w-full overflow-x-auto">
<Table className="overflow-hidden">
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id} className="bg-default-200">
{headerGroup.headers.map((header) => (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
className="h-[75px]"
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={columns.length} className="h-24 text-center">
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
<div className="flex items-center justify-center py-4 gap-2 flex-none">
<Button
variant="outline"
size="icon"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
className="w-8 h-8"
>
<ChevronLeft className="w-4 h-4" />
</Button>
{table.getPageOptions().map((page, pageIndex) => (
<Button
key={`basic-data-table-${pageIndex}`}
onClick={() => table.setPageIndex(pageIndex)}
size="icon"
className="w-8 h-8"
variant={
table.getState().pagination.pageIndex === pageIndex
? "default"
: "outline"
}
>
{page + 1}
</Button>
))}
<Button
variant="outline"
size="icon"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
className="w-8 h-8"
>
<ChevronRight className="w-4 h-4" />
</Button>
</div>
</div>
);
};
export default CompanyTable;

View File

@ -126,14 +126,14 @@ const EscalationTable = () => {
React.useEffect(() => {
fetchData();
}, [page, limit]);
}, [page, limit, search]);
async function fetchData() {
try {
const res = await getTicketingCollaborationPagination(
page - 1,
limit,
""
search
);
const data = res.data?.data;
const contentData = data?.content;
@ -149,10 +149,15 @@ const EscalationTable = () => {
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="flex justify-between items-center px-5">
<div>
<div className="mt-3">
<InputGroup merged>
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
<Search className=" h-4 w-4 dark:text-white" />
@ -161,6 +166,8 @@ const EscalationTable = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>

View File

@ -1,8 +1,7 @@
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormInternal from "@/components/form/communication/internal-form";
import FormCollaboration from "@/components/form/communication/collaboration-form";
const CollaborationCreatePage = async () => {
const CollaborationCreatePage = () => {
return (
<div>
<SiteBreadcrumb />

View File

@ -12,6 +12,7 @@ import {
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { format } from "date-fns";
import { Link } from "@/components/navigation";
const columns: ColumnDef<any>[] = [
{
@ -111,10 +112,14 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<Link
href={`/shared/communication/escalation/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit

View File

@ -125,11 +125,15 @@ const EscalationTable = () => {
React.useEffect(() => {
fetchData();
}, [page, limit]);
}, [page, limit, search]);
async function fetchData() {
try {
const res = await getTicketingEscalationPagination(page - 1, limit, "");
const res = await getTicketingEscalationPagination(
page - 1,
limit,
search
);
const data = res.data?.data;
const contentData = data?.content;
contentData.forEach((item: any, index: number) => {
@ -144,10 +148,15 @@ const EscalationTable = () => {
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="flex justify-between items-center px-5">
<div>
<div className="mt-3">
<InputGroup merged>
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
<Search className=" h-4 w-4 dark:text-white" />
@ -156,6 +165,8 @@ const EscalationTable = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>

View File

@ -0,0 +1,19 @@
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormTask from "@/components/form/task/task-form";
import FormTaskDetail from "@/components/form/task/task-detail-form";
import FormDetailInternal from "@/components/form/communication/internal-detail-form";
import FormDetailEscalation from "@/components/form/communication/escalation-detail-form";
const EscalationDetailPage = async () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<FormDetailEscalation />
</div>
</div>
);
};
export default EscalationDetailPage;

View File

@ -12,6 +12,7 @@ import {
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { format } from "date-fns";
import { Link } from "@/components/navigation";
const columns: ColumnDef<any>[] = [
{
@ -96,10 +97,14 @@ const columns: ColumnDef<any>[] = [
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="p-0" align="end">
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
<Link
href={`/shared/communication/internal/detail/${row.original.id}`}
>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<Eye className="w-4 h-4 me-1.5" />
View
</DropdownMenuItem>
</Link>
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
<SquarePen className="w-4 h-4 me-1.5" />
Edit

View File

@ -35,6 +35,7 @@ import {
Trash2,
TrendingDown,
TrendingUp,
UploadIcon,
} from "lucide-react";
import { cn, getCookiesDecrypt } from "@/lib/utils";
import {
@ -57,6 +58,7 @@ import {
listDataVideo,
} from "@/service/content/content";
import { listTicketingInternal } from "@/service/communication/communication";
import { Link } from "@/components/navigation";
const TableAudio = () => {
const router = useRouter();
@ -122,11 +124,11 @@ const TableAudio = () => {
React.useEffect(() => {
fetchData();
}, [page, limit]);
}, [page, limit, search]);
async function fetchData() {
try {
const res = await listTicketingInternal(page - 1, limit, "");
const res = await listTicketingInternal(page - 1, limit, search);
const data = res.data?.data;
const contentData = data?.content;
contentData.forEach((item: any, index: number) => {
@ -143,10 +145,21 @@ const TableAudio = () => {
}
}
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
setSearch(e.target.value); // Perbarui state search
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
};
return (
<div className="w-full overflow-x-auto">
<div className="w-full overflow-x-auto mt-3">
<div className="flex justify-between items-center px-5">
<div>
<div className="mt-3 flex flex-row items-center gap-2">
<Link href={"/shared/communication/internal/create"}>
<Button color="primary" className="text-white" size="md">
<UploadIcon />
Pertanyaan Baru
</Button>
</Link>
<InputGroup merged>
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
<Search className=" h-4 w-4 dark:text-white" />
@ -155,6 +168,8 @@ const TableAudio = () => {
type="text"
placeholder="Search Judul..."
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
value={search}
onChange={handleSearch}
/>
</InputGroup>
</div>

View File

@ -1,7 +1,7 @@
import SiteBreadcrumb from "@/components/site-breadcrumb";
import FormInternal from "@/components/form/communication/internal-form";
const InternalCreatePage = async () => {
const InternalCreatePage = () => {
return (
<div>
<SiteBreadcrumb />

Some files were not shown because too many files have changed in this diff Show More