feat:add table penugasan,perencanaan,indeks,agenda setting
This commit is contained in:
parent
655c72ee25
commit
73cc425d6a
|
|
@ -12,26 +12,27 @@ 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 {
|
||||
EventContentArg,
|
||||
} from '@fullcalendar/core'
|
||||
import { CalendarEvent, CalendarCategory } from "./data";
|
||||
import { EventContentArg } from "@fullcalendar/core";
|
||||
import EventModal from "./event-modal";
|
||||
import { useTranslations } from "next-intl";
|
||||
const wait = () => new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
interface CalendarViewProps {
|
||||
events: CalendarEvent[];
|
||||
categories: CalendarCategory[];
|
||||
|
||||
|
||||
}
|
||||
|
||||
const CalendarView = ({ events, categories }: CalendarViewProps) => {
|
||||
const [selectedCategory, setSelectedCategory] = useState<string[] | null>(null);
|
||||
const [selectedCategory, setSelectedCategory] = useState<string[] | null>(
|
||||
null
|
||||
);
|
||||
const [selectedEventDate, setSelectedEventDate] = useState<Date | null>(null);
|
||||
const [selectedEvent, setSelectedEvent] = useState<CalendarEvent | null>(null);
|
||||
const [draggableInitialized, setDraggableInitialized] = useState<boolean>(false);
|
||||
const t = useTranslations("CalendarApp")
|
||||
const [selectedEvent, setSelectedEvent] = useState<CalendarEvent | null>(
|
||||
null
|
||||
);
|
||||
const [draggableInitialized, setDraggableInitialized] =
|
||||
useState<boolean>(false);
|
||||
const t = useTranslations("CalendarApp");
|
||||
// event canvas state
|
||||
const [sheetOpen, setSheetOpen] = useState<boolean>(false);
|
||||
const [date, setDate] = React.useState<Date>(new Date());
|
||||
|
|
@ -103,30 +104,22 @@ const t = useTranslations("CalendarApp")
|
|||
if (selectedCategory && selectedCategory.includes(category)) {
|
||||
setSelectedCategory(selectedCategory.filter((c) => c !== category));
|
||||
} else {
|
||||
setSelectedCategory([...selectedCategory || [], category]);
|
||||
setSelectedCategory([...(selectedCategory || []), category]);
|
||||
}
|
||||
};
|
||||
|
||||
const handleClassName = (arg: EventContentArg) => {
|
||||
|
||||
if (arg.event.extendedProps.calendar === "holiday") {
|
||||
if (arg.event.extendedProps.calendar === "national") {
|
||||
return "destructive";
|
||||
}
|
||||
else if (arg.event.extendedProps.calendar === "business") {
|
||||
} else if (arg.event.extendedProps.calendar === "polda") {
|
||||
return "primary";
|
||||
} else if (arg.event.extendedProps.calendar === "personal") {
|
||||
} else if (arg.event.extendedProps.calendar === "polres") {
|
||||
return "success";
|
||||
} else if (arg.event.extendedProps.calendar === "family") {
|
||||
} else if (arg.event.extendedProps.calendar === "international") {
|
||||
return "info";
|
||||
} else if (arg.event.extendedProps.calendar === "etc") {
|
||||
return "info";
|
||||
} else if (arg.event.extendedProps.calendar === "meeting") {
|
||||
return "warning";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return "primary";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const filteredEvents = events?.filter((event) =>
|
||||
|
|
@ -144,7 +137,7 @@ const t = useTranslations("CalendarApp")
|
|||
className="dark:bg-background dark:text-foreground"
|
||||
>
|
||||
<Plus className="w-4 h-4 me-1" />
|
||||
{t("addEvent")}
|
||||
{"Tambahkan Agenda baru"}
|
||||
</Button>
|
||||
</CardHeader>
|
||||
<div className="px-3">
|
||||
|
|
@ -160,14 +153,14 @@ const t = useTranslations("CalendarApp")
|
|||
|
||||
<div id="external-events" className=" space-y-1.5 mt-6 px-4">
|
||||
<p className="text-sm font-medium text-default-700 mb-3">
|
||||
{t("shortDesc")}
|
||||
{t("shortDesc")}
|
||||
</p>
|
||||
{dragEvents.map((event) => (
|
||||
<ExternalDraggingevent key={event.id} event={event} />
|
||||
))}
|
||||
</div>
|
||||
<div className="py-4 text-default-800 font-semibold text-xs uppercase mt-4 mb-2 px-4">
|
||||
{t("filter")}
|
||||
{t("filter")}
|
||||
</div>
|
||||
<ul className="space-y-3 px-4">
|
||||
<li className=" flex gap-3">
|
||||
|
|
|
|||
|
|
@ -10,14 +10,14 @@ const nextMonth = date.getMonth() === 11 ? new Date(date.getFullYear() + 1, 0, 1
|
|||
const prevMonth = date.getMonth() === 11 ? new Date(date.getFullYear() - 1, 0, 1) : new Date(date.getFullYear(), date.getMonth() - 1, 1)
|
||||
export const calendarEvents = [
|
||||
{
|
||||
id: faker.string.uuid() ,
|
||||
id: faker.string.uuid(),
|
||||
title: "All Day Event",
|
||||
start: date,
|
||||
end: nextDay,
|
||||
allDay: false,
|
||||
//className: "warning",
|
||||
extendedProps: {
|
||||
calendar: "business",
|
||||
calendar: "polda",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -28,7 +28,7 @@ export const calendarEvents = [
|
|||
allDay: true,
|
||||
//className: "success",
|
||||
extendedProps: {
|
||||
calendar: "personal",
|
||||
calendar: "national",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -39,7 +39,7 @@ export const calendarEvents = [
|
|||
end: new Date(date.getFullYear(), date.getMonth() + 1, -7),
|
||||
// className: "info",
|
||||
extendedProps: {
|
||||
calendar: "family",
|
||||
calendar: "polres",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -50,7 +50,7 @@ export const calendarEvents = [
|
|||
allDay: true,
|
||||
//className: "primary",
|
||||
extendedProps: {
|
||||
calendar: "meeting",
|
||||
calendar: "polres",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -61,7 +61,7 @@ export const calendarEvents = [
|
|||
allDay: true,
|
||||
// className: "danger",
|
||||
extendedProps: {
|
||||
calendar: "holiday",
|
||||
calendar: "polda",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -72,84 +72,65 @@ export const calendarEvents = [
|
|||
allDay: true,
|
||||
//className: "primary",
|
||||
extendedProps: {
|
||||
calendar: "business",
|
||||
calendar: "international",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const calendarCategories = [
|
||||
export const calendarCategories = [
|
||||
{
|
||||
label: "Business",
|
||||
value: "business",
|
||||
label: "Nasional",
|
||||
value: "national",
|
||||
activeClass: "ring-primary-500 bg-primary-500",
|
||||
className: "group-hover:border-blue-500",
|
||||
},
|
||||
{
|
||||
label: "Personal",
|
||||
value: "personal",
|
||||
label: "Polda",
|
||||
value: "polda",
|
||||
activeClass: "ring-success-500 bg-success-500",
|
||||
className: " group-hover:border-green-500",
|
||||
},
|
||||
{
|
||||
label: "Holiday",
|
||||
value: "holiday",
|
||||
label: "Polres",
|
||||
value: "polres",
|
||||
activeClass: "ring-danger-500 bg-danger-500",
|
||||
className: " group-hover:border-red-500",
|
||||
},
|
||||
{
|
||||
label: "Family",
|
||||
value: "family",
|
||||
label: "Internasional",
|
||||
value: "international",
|
||||
activeClass: "ring-info-500 bg-info-500",
|
||||
className: " group-hover:border-cyan-500",
|
||||
},
|
||||
{
|
||||
label: "Meeting",
|
||||
value: "meeting",
|
||||
activeClass: "ring-warning-500 bg-warning-500",
|
||||
className: " group-hover:border-yellow-500",
|
||||
},
|
||||
{
|
||||
label: "Etc",
|
||||
value: "etc",
|
||||
activeClass: "ring-info-500 bg-info-500",
|
||||
className: " group-hover:border-cyan-500",
|
||||
}
|
||||
];
|
||||
|
||||
export const categories = [
|
||||
{
|
||||
label: "Business",
|
||||
value: "business",
|
||||
className: "data-[state=checked]:bg-primary data-[state=checked]:ring-primary",
|
||||
label: "Nasional",
|
||||
value: "national",
|
||||
className:
|
||||
"data-[state=checked]:bg-primary data-[state=checked]:ring-primary",
|
||||
},
|
||||
{
|
||||
label: "Personal",
|
||||
value: "personal",
|
||||
label: "Polda",
|
||||
value: "polda",
|
||||
|
||||
className: "data-[state=checked]:bg-success data-[state=checked]:ring-success",
|
||||
className:
|
||||
"data-[state=checked]:bg-success data-[state=checked]:ring-success",
|
||||
},
|
||||
{
|
||||
label: "Holiday",
|
||||
value: "holiday",
|
||||
className: "data-[state=checked]:bg-destructive data-[state=checked]:ring-destructive ",
|
||||
label: "Polres",
|
||||
value: "polres",
|
||||
className:
|
||||
"data-[state=checked]:bg-destructive data-[state=checked]:ring-destructive ",
|
||||
},
|
||||
{
|
||||
label: "Family",
|
||||
value: "family",
|
||||
label: "Internasional",
|
||||
value: "international",
|
||||
className: "data-[state=checked]:bg-info data-[state=checked]:ring-info ",
|
||||
},
|
||||
{
|
||||
label: "Meeting",
|
||||
value: "meeting",
|
||||
className: "data-[state=checked]:bg-warning data-[state=checked]:ring-warning",
|
||||
},
|
||||
{
|
||||
label: "Etc",
|
||||
value: "etc",
|
||||
className: "data-[state=checked]:bg-info data-[state=checked]:ring-info",
|
||||
}
|
||||
];
|
||||
|
||||
export type CalendarEvent = (typeof calendarEvents)[number]
|
||||
export type CalendarCategory = (typeof calendarCategories)[number]
|
||||
export type Category = (typeof categories)[number]
|
||||
export type CalendarEvent = (typeof calendarEvents)[number];
|
||||
export type CalendarCategory = (typeof calendarCategories)[number];
|
||||
export type Category = (typeof categories)[number];
|
||||
|
|
|
|||
|
|
@ -1,5 +1,36 @@
|
|||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import MediahubTable from "../planning/mediahub/table-mediahub/mediahub-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { UploadIcon } from "lucide-react";
|
||||
import BlogTable from "./table-blog/mediahub-table";
|
||||
|
||||
const BlogPage = async () => {
|
||||
return <div></div>;
|
||||
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 Indeks
|
||||
</div>
|
||||
<div>
|
||||
<Button color="primary" className="text-white">
|
||||
<UploadIcon />
|
||||
Tambah Indeks
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
<BlogTable />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogPage;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
export const data = [
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
status: "Terkirim",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
"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 = {
|
||||
title: string;
|
||||
category: string;
|
||||
date: string;
|
||||
tag: string;
|
||||
status: string;
|
||||
};
|
||||
import { data } from "./data";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { InputGroup, InputGroupText } from "@/components/ui/input-group";
|
||||
|
||||
export const columns: ColumnDef<CompanyData>[] = [
|
||||
{
|
||||
accessorKey: "title",
|
||||
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("title")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "category",
|
||||
header: "Kategori ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("category")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "date",
|
||||
header: "Tanggal Unggah ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("date")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "tag",
|
||||
header: "Tag ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("tag")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "status",
|
||||
header: "Status",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<span className="whitespace-nowrap text-blue-600">
|
||||
{row.getValue("status")}
|
||||
</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 BlogTable = () => {
|
||||
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">
|
||||
<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 BlogTable;
|
||||
|
|
@ -15,19 +15,19 @@ const RecentActivity = () => {
|
|||
<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-2xl">0 FOTO</p>
|
||||
<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-2xl">0 AUDIO VISUAL</p>
|
||||
<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-2xl">0 TEXT</p>
|
||||
<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-2xl">0 AUDIO</p>
|
||||
<p className="text-xl">0 AUDIO</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ const DashboardPage = () => {
|
|||
<div className="lg:col-span-4 col-span-12">
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center">
|
||||
<CardTitle className="flex-1">
|
||||
<CardTitle className="flex-1 text-lg">
|
||||
{"Total Produksi Konten"}
|
||||
</CardTitle>
|
||||
<DashboardDropdown />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,30 @@
|
|||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { UploadIcon } from "lucide-react";
|
||||
import TaskTable from "../../task/table-task/task-table";
|
||||
import MediahubTable from "./table-mediahub/mediahub-table";
|
||||
|
||||
const MediahubPage = async () => {
|
||||
return <div></div>;
|
||||
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">
|
||||
Perencanaan : Kanal MediaHub
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
<MediahubTable />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MediahubPage;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
export const data = [
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
"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 = {
|
||||
title: string;
|
||||
date: string;
|
||||
status: string;
|
||||
};
|
||||
import { data } from "./data";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { InputGroup, InputGroupText } from "@/components/ui/input-group";
|
||||
|
||||
export const columns: ColumnDef<CompanyData>[] = [
|
||||
{
|
||||
accessorKey: "title",
|
||||
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("title")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "date",
|
||||
header: "Tanggal Unggah ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("date")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "status",
|
||||
header: "Status",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<span className="whitespace-nowrap text-blue-600">
|
||||
{row.getValue("status")}
|
||||
</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 MediahubTable = () => {
|
||||
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">
|
||||
<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 MediahubTable;
|
||||
|
|
@ -1,5 +1,27 @@
|
|||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import MedsosTable from "./table-medsos/medsos-table";
|
||||
|
||||
const MedsosMediahubPage = async () => {
|
||||
return <div></div>;
|
||||
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">
|
||||
Perencanaan : Kanal Medsos
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
<MedsosTable />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MedsosMediahubPage;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
export const data = [
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
date: "15/10/2024 9:11",
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
"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 = {
|
||||
title: string;
|
||||
date: string;
|
||||
status: string;
|
||||
};
|
||||
import { data } from "./data";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { InputGroup, InputGroupText } from "@/components/ui/input-group";
|
||||
|
||||
export const columns: ColumnDef<CompanyData>[] = [
|
||||
{
|
||||
accessorKey: "title",
|
||||
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("title")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "date",
|
||||
header: "Tanggal Unggah ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("date")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "status",
|
||||
header: "Status",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<span className="whitespace-nowrap text-blue-600">
|
||||
{row.getValue("status")}
|
||||
</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 MedsosTable = () => {
|
||||
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">
|
||||
<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 MedsosTable;
|
||||
|
|
@ -1,5 +1,35 @@
|
|||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import TaskTable from "./table-task/task-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { UploadIcon } from "lucide-react";
|
||||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||
|
||||
const TaskPage = async () => {
|
||||
return <div></div>;
|
||||
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 Penugasan
|
||||
</div>
|
||||
<div>
|
||||
<Button color="primary" className="text-white">
|
||||
<UploadIcon />
|
||||
Buat Penugasan
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
<TaskTable />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TaskPage;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,106 @@
|
|||
export const data = [
|
||||
{
|
||||
title: "Giat Pimpinan",
|
||||
code: "PNMH-1287",
|
||||
status: "paid",
|
||||
date: "$231.26",
|
||||
category: "amplifikasi",
|
||||
typeTask: "Mediahub",
|
||||
},
|
||||
{
|
||||
title: "Liputan Kegiatan",
|
||||
code: "PNMH-1287",
|
||||
status: "due",
|
||||
date: "$432.81",
|
||||
category: "amplifikasi",
|
||||
typeTask: "Mediahub",
|
||||
},
|
||||
{
|
||||
title: "Giat Pimpinan",
|
||||
code: "PNMH-1287",
|
||||
status: "due",
|
||||
date: "$437.65",
|
||||
category: "amplifikasi",
|
||||
typeTask: "Mediahub",
|
||||
},
|
||||
{
|
||||
title: "Pers Rilis",
|
||||
code: "PNMH-1287",
|
||||
status: "canceled",
|
||||
date: "$387.55",
|
||||
category: "amplifikasi",
|
||||
typeTask: "Mediahub",
|
||||
},
|
||||
{
|
||||
title: "Giat Pimpinan",
|
||||
code: "PNMH-1287",
|
||||
status: "canceled",
|
||||
date: "$489.80",
|
||||
category: "amplifikasi",
|
||||
typeTask: "Mediahub",
|
||||
},
|
||||
{
|
||||
title: "Liputan Kegiatan",
|
||||
code: "PNMH-1287",
|
||||
status: "canceled",
|
||||
date: "$421.45",
|
||||
category: "amplifikasi",
|
||||
typeTask: "Mediahub",
|
||||
},
|
||||
{
|
||||
title: "Pers Rilis",
|
||||
code: "PNMH-1287",
|
||||
status: "canceled",
|
||||
date: "$207.61",
|
||||
category: "amplifikasi",
|
||||
typeTask: "Mediahub",
|
||||
},
|
||||
{
|
||||
title: "Giat Pimpinan",
|
||||
code: "PNMH-1287",
|
||||
status: "paid",
|
||||
date: "$392.86",
|
||||
category: "amplifikasi",
|
||||
typeTask: "Mediahub",
|
||||
},
|
||||
{
|
||||
title: "Pers Rilis",
|
||||
code: "PNMH-1287",
|
||||
status: "paid",
|
||||
date: "$162.87",
|
||||
category: "amplifikasi",
|
||||
typeTask: "Mediahub",
|
||||
},
|
||||
{
|
||||
title: "Giat Pimpinan",
|
||||
code: "PNMH-1287",
|
||||
status: "paid",
|
||||
date: "$268.58",
|
||||
category: "amplifikasi",
|
||||
typeTask: "Mediahub",
|
||||
},
|
||||
{
|
||||
title: "Liputan Kegiatan",
|
||||
code: "PNMH-1287",
|
||||
status: "paid",
|
||||
date: "$369.19",
|
||||
category: "amplifikasi",
|
||||
typeTask: "Mediahub",
|
||||
},
|
||||
{
|
||||
title: "Liputan Kegiatan",
|
||||
code: "PNMH-1287",
|
||||
status: "paid",
|
||||
date: "$420.87",
|
||||
category: "amplifikasi",
|
||||
typeTask: "Mediahub",
|
||||
},
|
||||
{
|
||||
title: "Giat Pimpinan",
|
||||
code: "PNMH-1287",
|
||||
status: "paid",
|
||||
date: "$420.26",
|
||||
category: "amplifikasi",
|
||||
typeTask: "Mediahub",
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,298 @@
|
|||
"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 = {
|
||||
title: string;
|
||||
code: string;
|
||||
typeTask: string;
|
||||
category: string;
|
||||
date: string;
|
||||
status: string;
|
||||
};
|
||||
import { data } from "./data";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { InputGroup, InputGroupText } from "@/components/ui/input-group";
|
||||
|
||||
export const columns: ColumnDef<CompanyData>[] = [
|
||||
{
|
||||
accessorKey: "title",
|
||||
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("title")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "code",
|
||||
header: "Kode ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("code")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "typeTask",
|
||||
header: "Kode ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("typeTask")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "category",
|
||||
header: "Jenis Tugas ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("category")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "date",
|
||||
header: "Tanggal Unggah ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("date")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
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 TaskTable = () => {
|
||||
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">
|
||||
<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 TaskTable;
|
||||
Loading…
Reference in New Issue