feat:add table konten, dashboard

This commit is contained in:
Anang Yusman 2024-11-29 00:23:53 +07:00
parent ead5912044
commit 655c72ee25
88 changed files with 4359 additions and 7007 deletions

View File

@ -1,7 +1,9 @@
export const metadata = {
title: "Video",
};
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Dashcode Next Js",
description: "Dashcode is a popular dashboard template.",
};
const Layout = ({ children }: { children: React.ReactNode }) => {
return <>{children}</>;
};

View File

@ -1,5 +1,79 @@
const VideoPage = async () => {
return <div></div>;
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import TableImage from "./table-video";
import { Newspaper, NewspaperIcon, UploadIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Icon } from "@iconify/react/dist/iconify.js";
import TableVideo from "./table-video";
const ReactTableVideoPage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<Card className="py-4 px-3">
<div className="flex flex-row justify-between items-center px-5">
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="icon-park-outline:check-one" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah disetujui hari ini</p>
</div>
</div>
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="material-symbols:settings-backup-restore-rounded" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah direvisi hari ini</p>
</div>
</div>
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="healthicons:no-outline" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah ditolak hari ini</p>
</div>
</div>
</div>
</Card>
<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">
Konten Video
</div>
<div>
<Button color="primary" className="text-white">
<UploadIcon />
Unggah Video
</Button>
<Button color="primary" className="text-white ml-3">
<UploadIcon />
Unggah Video Dengan AI
</Button>
</div>
</div>
</Card>
<Card>
<CardContent className="p-0">
<TableVideo />
</CardContent>
</Card>
</div>
</div>
);
};
export default VideoPage;
export default ReactTableVideoPage;

View File

@ -0,0 +1,180 @@
"use client";
import { ColumnDef } from "@tanstack/react-table";
import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
export type DataProps = {
id: string | number;
order: string;
customer: {
name: string;
};
date: string;
quantity: number;
amount: string;
status: "paid" | "due" | "canceled";
action: React.ReactNode;
};
export const columns: ColumnDef<DataProps>[] = [
// {
// id: "select",
// header: ({ table }) => (
// <Checkbox
// checked={
// table.getIsAllPageRowsSelected() ||
// (table.getIsSomePageRowsSelected() && "indeterminate")
// }
// onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
// aria-label="Select all"
// />
// ),
// cell: ({ row }) => (
// <div className="xl:w-16">
// <Checkbox
// checked={row.getIsSelected()}
// onCheckedChange={(value) => row.toggleSelected(!!value)}
// aria-label="Select row"
// />
// </div>
// ),
// enableSorting: false,
// enableHiding: false,
// },
{
accessorKey: "id",
header: "No",
cell: ({ row }) => <span>{row.getValue("id")}</span>,
},
{
accessorKey: "order",
header: "Judul",
cell: ({ row }) => (
<div className="w-52">
<span>{row.getValue("order")}</span>,
</div>
),
},
{
accessorKey: "customer",
header: "Kategory",
cell: ({ row }) => {
const user = row.original.customer;
return (
<div className="font-medium text-card-foreground/80">
<div className="flex gap-3 items-center">
<span className="text-sm text-default-600 whitespace-nowrap">
{user?.name ?? "Unknown User"}
</span>
</div>
</div>
);
},
},
{
accessorKey: "date",
header: "Tanggal unggah",
cell: ({ row }) => {
return <span>{row.getValue("date")}</span>;
},
},
{
accessorKey: "quantity",
header: "Kreator",
cell: ({ row }) => {
return <span>{row.getValue("quantity")}</span>;
},
},
{
accessorKey: "amount",
header: "Sumber",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "amount",
header: "Penempatan File",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
paid: "bg-success/20 text-success",
due: "bg-warning/20 text-warning",
canceled: "bg-destructive/20 text-destructive",
};
const status = row.getValue<string>("status");
const statusStyles = statusColors[status] || "default";
return (
<Badge className={cn("rounded-full px-5", statusStyles)}>
{status}{" "}
</Badge>
);
},
},
{
accessorKey: "amount",
header: "Kurasi Konten",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "amount",
header: "Saran",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</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>
);
},
},
];

View File

@ -0,0 +1,184 @@
import { DataProps } from "./columns";
export const data: DataProps[] = [
{
id: 1,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "3/26/2022",
quantity: 13,
amount: "$1779.53",
status: "paid",
action: null,
},
{
id: 2,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "2/6/2022",
quantity: 13,
amount: "$2215.78",
status: "due",
action: null,
},
{
id: 3,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "9/6/2021",
quantity: 1,
amount: "$3183.60",
status: "due",
action: null,
},
{
id: 4,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "11/7/2021",
quantity: 13,
amount: "$2587.86",
status: "canceled",
action: null,
},
{
id: 5,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Rachel Brown",
},
date: "5/6/2022",
quantity: 12,
amount: "$3840.73",
status: "paid",
action: null,
},
{
id: 6,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Megan Taylor",
},
date: "2/14/2022",
quantity: 12,
amount: "$4764.18",
status: "canceled",
action: null,
},
{
id: 7,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Sophie Clark",
},
date: "7/30/2022",
quantity: 6,
amount: "$2875.05",
status: "paid",
action: null,
},
{
id: 8,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Natalie Martin",
},
date: "6/30/2022",
quantity: 9,
amount: "$2491.02",
status: "due",
action: null,
},
{
id: 9,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Hannah Lewis",
},
date: "8/9/2022",
quantity: 8,
amount: "$3006.95",
status: "due",
action: null,
},
{
id: 10,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Lisa White",
},
date: "8/4/2022",
quantity: 12,
amount: "$2160.32",
status: "paid",
action: null,
},
{
id: 11,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Emma Walker",
},
date: "4/5/2022",
quantity: 8,
amount: "$1272.66",
status: "paid",
action: null,
},
{
id: 12,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "8/9/2022",
quantity: 2,
amount: "$4327.86",
status: "canceled",
action: null,
},
{
id: 13,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "2/10/2022",
quantity: 11,
amount: "$3671.81",
status: "canceled",
action: null,
},
{
id: 14,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "2/10/2022",
quantity: 2,
amount: "$3401.82",
status: "paid",
action: null,
},
{
id: 15,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "5/20/2022",
quantity: 4,
amount: "$2387.49",
status: "canceled",
action: null,
},
];

View File

@ -1,6 +1,6 @@
"use client"
"use client";
import * as React from "react"
import * as React from "react";
import {
ColumnFiltersState,
SortingState,
@ -11,10 +11,9 @@ import {
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table"
import { columns } from "./columns"
import { Input } from "@/components/ui/input"
} from "@tanstack/react-table";
import { columns } from "./columns";
import { Input } from "@/components/ui/input";
import {
Table,
@ -23,18 +22,19 @@ import {
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
import { useTranslations } from "next-intl";
import { data } from "./data"
} from "@/components/ui/table";
const TransactionsTable = () => {
const [sorting, setSorting] = React.useState<SortingState>([])
import { data } from "./data";
import TablePagination from "./table-pagination";
const TableVideo = () => {
const [sorting, setSorting] = React.useState<SortingState>([]);
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
)
);
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({})
const [rowSelection, setRowSelection] = React.useState({})
React.useState<VisibilityState>({});
const [rowSelection, setRowSelection] = React.useState({});
const table = useReactTable({
data,
@ -53,14 +53,11 @@ const TransactionsTable = () => {
columnVisibility,
rowSelection,
},
})
const t = useTranslations("BankingDashboard");
});
return (
<div className="w-full">
<div className="flex items-center py-5 px-5">
<div className="flex-1 text-2xl font-semibold leading-none tracking-tight">
{t("all_transactions")}
</div>
<div className="flex items-center py-4 px-5">
<div className="flex-none">
<Input
placeholder="Filter Status..."
@ -81,7 +78,7 @@ const t = useTranslations("BankingDashboard");
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id} className="last:text-end">
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
@ -117,7 +114,8 @@ const t = useTranslations("BankingDashboard");
)}
</TableBody>
</Table>
<TablePagination table={table} />
</div>
);
}
export default TransactionsTable;
};
export default TableVideo;

View File

@ -1,7 +1,6 @@
import { Button } from '@/components/ui/button';
import { Table } from '@tanstack/react-table';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import React from 'react';
interface DataTablePaginationProps {
table: Table<any>;
@ -29,7 +28,8 @@ const TablePagination = ({ table }: DataTablePaginationProps) => {
key={`basic-data-table-${pageIndex}`}
onClick={() => table.setPageIndex(pageIndex)}
size="icon"
className={`w-8 h-8 hover:text-primary-foreground ${table.getState().pagination.pageIndex === pageIndex ? 'bg-default' : 'bg-default-300 text-default'}`}
className="w-8 h-8"
variant={table.getState().pagination.pageIndex === pageIndex ? 'default' : 'outline'}
>
{page + 1}
</Button>

View File

@ -1,243 +0,0 @@
"use client";
import React, { useState, useEffect } from "react";
import FullCalendar from "@fullcalendar/react"; // must go before plugins
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin, { Draggable } from "@fullcalendar/interaction";
import listPlugin from "@fullcalendar/list";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import ExternalDraggingevent from "./dragging-events";
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 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 [selectedEventDate, setSelectedEventDate] = useState<Date | null>(null);
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());
const [dragEvents] = useState([
{ title: "New Event Planning", id: "101", tag: "business" },
{ title: "Meeting", id: "102", tag: "meeting" },
{ title: "Generating Reports", id: "103", tag: "holiday" },
{ title: "Create New theme", id: "104", tag: "etc" },
]);
useEffect(() => {
setSelectedCategory(categories?.map((c) => c.value));
}, [events, categories]);
useEffect(() => {
const draggableEl = document.getElementById("external-events");
const initDraggable = () => {
if (draggableEl) {
new Draggable(draggableEl, {
itemSelector: ".fc-event",
eventData: function (eventEl) {
let title = eventEl.getAttribute("title");
let id = eventEl.getAttribute("data");
let event = dragEvents.find((e) => e.id === id);
let tag = event ? event.tag : "";
return {
title: title,
id: id,
extendedProps: {
calendar: tag,
},
};
},
});
}
};
if (dragEvents.length > 0) {
initDraggable();
}
return () => {
draggableEl?.removeEventListener("mousedown", initDraggable);
};
}, [dragEvents]);
// event click
const handleEventClick = (arg: any) => {
setSelectedEventDate(null);
setSheetOpen(true);
setSelectedEvent(arg);
wait().then(() => (document.body.style.pointerEvents = "auto"));
};
// handle close modal
const handleCloseModal = () => {
setSheetOpen(false);
setSelectedEvent(null);
setSelectedEventDate(null);
};
const handleDateClick = (arg: any) => {
setSheetOpen(true);
setSelectedEventDate(arg);
setSelectedEvent(null);
wait().then(() => (document.body.style.pointerEvents = "auto"));
};
const handleCategorySelection = (category: string) => {
if (selectedCategory && selectedCategory.includes(category)) {
setSelectedCategory(selectedCategory.filter((c) => c !== category));
} else {
setSelectedCategory([...selectedCategory || [], category]);
}
};
const handleClassName = (arg: EventContentArg) => {
if (arg.event.extendedProps.calendar === "holiday") {
return "destructive";
}
else if (arg.event.extendedProps.calendar === "business") {
return "primary";
} else if (arg.event.extendedProps.calendar === "personal") {
return "success";
} else if (arg.event.extendedProps.calendar === "family") {
return "info";
} else if (arg.event.extendedProps.calendar === "etc") {
return "info";
} else if (arg.event.extendedProps.calendar === "meeting") {
return "warning";
}
else {
return "primary";
}
};
const filteredEvents = events?.filter((event) =>
selectedCategory?.includes(event.extendedProps.calendar)
);
return (
<>
<div className="grid grid-cols-12 gap-6 divide-x divide-border">
<Card className="col-span-12 lg:col-span-4 2xl:col-span-3 pb-5">
<CardContent className="p-0">
<CardHeader className="border-none mb-2 pt-5">
<Button
onClick={handleDateClick}
className="dark:bg-background dark:text-foreground"
>
<Plus className="w-4 h-4 me-1" />
{t("addEvent")}
</Button>
</CardHeader>
<div className="px-3">
<Calendar
mode="single"
selected={date}
onSelect={(s) => {
handleDateClick(s);
}}
className="rounded-md border w-full p-0 border-none"
/>
</div>
<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")}
</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")}
</div>
<ul className="space-y-3 px-4">
<li className=" flex gap-3">
<Checkbox
checked={selectedCategory?.length === categories?.length}
onClick={() => {
if (selectedCategory?.length === categories?.length) {
setSelectedCategory([]);
} else {
setSelectedCategory(categories.map((c) => c.value));
}
}}
/>
<Label>All</Label>
</li>
{categories?.map((category) => (
<li className="flex gap-3 " key={category.value}>
<Checkbox
className={category.className}
id={category.label}
checked={selectedCategory?.includes(category.value)}
onClick={() => handleCategorySelection(category.value)}
/>
<Label htmlFor={category.label}>{category.label}</Label>
</li>
))}
</ul>
</CardContent>
</Card>
<Card className="col-span-12 lg:col-span-8 2xl:col-span-9 pt-5">
<CardContent className="dashcode-app-calendar">
<FullCalendar
plugins={[
dayGridPlugin,
timeGridPlugin,
interactionPlugin,
listPlugin,
]}
headerToolbar={{
left: "prev,next today",
center: "title",
right: "dayGridMonth,timeGridWeek,timeGridDay,listWeek",
}}
events={filteredEvents}
editable={true}
rerenderDelay={10}
eventDurationEditable={false}
selectable={true}
selectMirror={true}
droppable={true}
dayMaxEvents={2}
weekends={true}
eventClassNames={handleClassName}
dateClick={handleDateClick}
eventClick={handleEventClick}
initialView="dayGridMonth"
/>
</CardContent>
</Card>
</div>
<EventModal
open={sheetOpen}
onClose={handleCloseModal}
categories={categories}
event={selectedEvent}
selectedDate={selectedEventDate}
/>
</>
);
};
export default CalendarView;

View File

@ -1,155 +0,0 @@
import { faker } from "@faker-js/faker";
const date = new Date();
const prevDay = new Date().getDate() - 1;
const nextDay = new Date(new Date().getTime() + 24 * 60 * 60 * 1000);
// prettier-ignore
const nextMonth = date.getMonth() === 11 ? new Date(date.getFullYear() + 1, 0, 1) : new Date(date.getFullYear(), date.getMonth() + 1, 1)
// prettier-ignore
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() ,
title: "All Day Event",
start: date,
end: nextDay,
allDay: false,
//className: "warning",
extendedProps: {
calendar: "business",
},
},
{
id: faker.string.uuid(),
title: "Meeting With Client",
start: new Date(date.getFullYear(), date.getMonth() + 1, -11),
end: new Date(date.getFullYear(), date.getMonth() + 1, -10),
allDay: true,
//className: "success",
extendedProps: {
calendar: "personal",
},
},
{
id: faker.string.uuid(),
title: "Lunch",
allDay: true,
start: new Date(date.getFullYear(), date.getMonth() + 1, -9),
end: new Date(date.getFullYear(), date.getMonth() + 1, -7),
// className: "info",
extendedProps: {
calendar: "family",
},
},
{
id: faker.string.uuid(),
title: "Birthday Party",
start: new Date(date.getFullYear(), date.getMonth() + 1, -11),
end: new Date(date.getFullYear(), date.getMonth() + 1, -10),
allDay: true,
//className: "primary",
extendedProps: {
calendar: "meeting",
},
},
{
id: faker.string.uuid(),
title: "Birthday Party",
start: new Date(date.getFullYear(), date.getMonth() + 1, -13),
end: new Date(date.getFullYear(), date.getMonth() + 1, -12),
allDay: true,
// className: "danger",
extendedProps: {
calendar: "holiday",
},
},
{
id: faker.string.uuid(),
title: "Monthly Meeting",
start: nextMonth,
end: nextMonth,
allDay: true,
//className: "primary",
extendedProps: {
calendar: "business",
},
},
];
export const calendarCategories = [
{
label: "Business",
value: "business",
activeClass: "ring-primary-500 bg-primary-500",
className: "group-hover:border-blue-500",
},
{
label: "Personal",
value: "personal",
activeClass: "ring-success-500 bg-success-500",
className: " group-hover:border-green-500",
},
{
label: "Holiday",
value: "holiday",
activeClass: "ring-danger-500 bg-danger-500",
className: " group-hover:border-red-500",
},
{
label: "Family",
value: "family",
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: "Personal",
value: "personal",
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: "Family",
value: "family",
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]

View File

@ -1,23 +0,0 @@
import { cn } from "@/lib/utils";
const ExternalDraggingevent = ({ event }: any) => {
const { title, id, tag } = event;
return (
<div
title={title}
data-id={id}
className="fc-event px-4 py-1.5 bg-default-100 dark:bg-default-300 rounded text-sm flex items-center gap-2 shadow-sm cursor-move" >
<span
className={cn("h-2 w-2 rounded-full block", {
"bg-primary": tag === "business",
"bg-warning": tag === "meeting",
"bg-destructive": tag === "holiday",
"bg-info": tag === "etc",
})}
></span>
<span className="text-sm font-medium text-default-900">{title}</span>
</div>
);
};
export default ExternalDraggingevent;

View File

@ -1,277 +0,0 @@
"use client"
import React, { useState, useEffect } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useForm, Controller } from "react-hook-form";
import { cn, } from "@/lib/utils";
import { format } from "date-fns"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Calendar } from "@/components/ui/calendar";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { Loader2, CalendarIcon } from "lucide-react";
import DeleteConfirmationDialog from "@/components/delete-confirmation-dialog";
import { CalendarCategory } from "./data";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
const schema = z.object({
title: z.string().min(3, { message: "Required" }),
});
const EventModal = ({ open, onClose, categories, event, selectedDate }: {
open: boolean;
onClose: () => void;
categories: any;
event: any;
selectedDate: any
}) => {
const [startDate, setStartDate] = useState<Date>(new Date());
const [endDate, setEndDate] = useState<Date>(new Date());
const [isPending, startTransition] = React.useTransition();
const [calendarProps, setCalendarProps] = React.useState<any>(categories[0].value);
// delete modal state
const [deleteModalOpen, setDeleteModalOpen] = useState<boolean>(false);
const [eventIdToDelete, setEventIdToDelete] = useState<string | null>(null);
const {
register,
control,
reset,
setValue,
formState: { errors },
handleSubmit,
} = useForm({
resolver: zodResolver(schema),
mode: "all",
});
const onSubmit = (data: any) => {
startTransition(async () => {
if (!event) {
data.start = startDate;
data.end = endDate;
data.allDay = false;
data.extendedProps = {
calendar: calendarProps,
};
}
if (event) {
}
});
};
useEffect(() => {
if (selectedDate) {
setStartDate(selectedDate.date);
setEndDate(selectedDate.date);
}
if (event) {
setStartDate(event?.event?.start);
setEndDate(event?.event?.end);
const eventCalendar = event?.event?.extendedProps?.calendar;
if (eventCalendar) {
setCalendarProps(eventCalendar);
} else {
setCalendarProps(categories[0].value);
}
}
setValue("title", event?.event?.title || "");
}, [event, selectedDate, open, categories, setValue]);
const onDeleteEventAction = async () => {
try {
} catch (error) {
}
};
const handleOpenDeleteModal = (eventId: string) => {
setEventIdToDelete(eventId);
setDeleteModalOpen(true);
onClose();
};
return (
<>
<DeleteConfirmationDialog
open={deleteModalOpen}
onClose={() => setDeleteModalOpen(false)}
onConfirm={onDeleteEventAction}
defaultToast={false}
/>
<Dialog open={open} onOpenChange={onClose}>
<DialogContent
onPointerDownOutside={onClose}
>
<DialogHeader>
<DialogTitle>
{event ? "Edit Event" : "Create Event"} {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>
<Input
id="title"
type="text"
placeholder="Enter Event Name"
{...register("title")}
/>
{errors?.title?.message && (
<div className="text-destructive text-sm">
{typeof errors?.title?.message === 'string'
? errors?.title?.message
: JSON.stringify(errors?.title?.message)}
</div>
)}
</div>
<div className="space-y-1.5">
<Label htmlFor="startDate">Start Date </Label>
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
size="md"
className={cn(
"w-full justify-between text-left font-normal border-default-200 text-default-600 md:px-4",
!startDate && "text-muted-foreground"
)}
>
{startDate ? (
format(startDate, "PP")
) : (
<span>Pick a date</span>
)}
<CalendarIcon className="h-4 w-4" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Controller
name="startDate"
control={control}
render={({ field }) => (
<Calendar
mode="single"
selected={startDate}
onSelect={(date) => setStartDate(date as Date)}
initialFocus
/>
)}
/>
</PopoverContent>
</Popover>
</div>
<div className="space-y-1.5">
<Label htmlFor="endDate">End Date</Label>
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
size="md"
className={cn(
"w-full justify-between text-left font-normal border-default-200 text-default-600 md:px-4",
!endDate && "text-muted-foreground"
)}
>
{endDate ? (
format(endDate, "PP")
) : (
<span>Pick a date</span>
)}
<CalendarIcon className="h-4 w-4" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Controller
name="endDate"
control={control}
render={({ field }) => (
<Calendar
mode="single"
selected={endDate}
onSelect={(date) => setEndDate(date as Date)}
initialFocus
/>
)}
/>
</PopoverContent>
</Popover>
</div>
<div className="space-y-1.5">
<Label htmlFor="calendarProps">Label </Label>
<Controller
name="calendarProps"
control={control}
render={({ field }) => (
<Select
value={calendarProps}
onValueChange={(data) => setCalendarProps(data)}
>
<SelectTrigger>
<SelectValue placeholder="Label" />
</SelectTrigger>
<SelectContent>
{categories.map((category: CalendarCategory) => (
<SelectItem
value={category.value}
key={category.value}
>
{category.label}
</SelectItem>
))}
</SelectContent>
</Select>
)}
/>
</div>
</div>
<div className="flex flex-wrap gap-2 mt-10">
<Button type="submit" disabled={isPending} className="flex-1">
{isPending ? (
<>
<Loader2 className="me-2 h-4 w-4 animate-spin" />
{event ? "Updating..." : "Adding..."}
</>
) : event ? (
"Update Event"
) : (
"Add Event"
)}
</Button>
{event && (
<Button
type="button"
color="destructive"
onClick={() => handleOpenDeleteModal(event?.event?.id)}
className="flex-1"
>
Delete
</Button>
)}
</div>
</form>
</div>
</DialogContent>
</Dialog>
</>
);
};
export default EventModal;

View File

@ -1,7 +1,9 @@
export const metadata = {
title: "Audio",
};
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Dashcode Next Js",
description: "Dashcode is a popular dashboard template.",
};
const Layout = ({ children }: { children: React.ReactNode }) => {
return <>{children}</>;
};

View File

@ -1,21 +1,79 @@
import { getEvents, getCategories } from "./utils";
import { Category } from "./data"
import CalendarView from "./calender-view";
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import TableImage from "./table-audio";
import { Newspaper, NewspaperIcon, UploadIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Icon } from "@iconify/react/dist/iconify.js";
import TableAudio from "./table-audio";
const CalenderPage = async () => {
const events = await getEvents();
const categories = await getCategories();
const formattedCategories = categories.map((category: Category) => ({
...category,
activeClass: "",
}));
const ReactTableAudioPage = () => {
return (
<div>
<CalendarView events={events} categories={formattedCategories} />
<SiteBreadcrumb />
<div className="space-y-4">
<Card className="py-4 px-3">
<div className="flex flex-row justify-between items-center px-5">
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="icon-park-outline:check-one" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah disetujui hari ini</p>
</div>
</div>
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="material-symbols:settings-backup-restore-rounded" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah direvisi hari ini</p>
</div>
</div>
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="healthicons:no-outline" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah ditolak hari ini</p>
</div>
</div>
</div>
</Card>
<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">
Konten Audio
</div>
<div>
<Button color="primary" className="text-white">
<UploadIcon />
Unggah Audio
</Button>
<Button color="primary" className="text-white ml-3">
<UploadIcon />
Unggah Audio Dengan AI
</Button>
</div>
</div>
</Card>
<Card>
<CardContent className="p-0">
<TableAudio />
</CardContent>
</Card>
</div>
</div>
);
};
export default CalenderPage;
export default ReactTableAudioPage;

View File

@ -0,0 +1,180 @@
"use client";
import { ColumnDef } from "@tanstack/react-table";
import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
export type DataProps = {
id: string | number;
order: string;
customer: {
name: string;
};
date: string;
quantity: number;
amount: string;
status: "paid" | "due" | "canceled";
action: React.ReactNode;
};
export const columns: ColumnDef<DataProps>[] = [
// {
// id: "select",
// header: ({ table }) => (
// <Checkbox
// checked={
// table.getIsAllPageRowsSelected() ||
// (table.getIsSomePageRowsSelected() && "indeterminate")
// }
// onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
// aria-label="Select all"
// />
// ),
// cell: ({ row }) => (
// <div className="xl:w-16">
// <Checkbox
// checked={row.getIsSelected()}
// onCheckedChange={(value) => row.toggleSelected(!!value)}
// aria-label="Select row"
// />
// </div>
// ),
// enableSorting: false,
// enableHiding: false,
// },
{
accessorKey: "id",
header: "No",
cell: ({ row }) => <span>{row.getValue("id")}</span>,
},
{
accessorKey: "order",
header: "Judul",
cell: ({ row }) => (
<div className="w-52">
<span>{row.getValue("order")}</span>,
</div>
),
},
{
accessorKey: "customer",
header: "Kategory",
cell: ({ row }) => {
const user = row.original.customer;
return (
<div className="font-medium text-card-foreground/80">
<div className="flex gap-3 items-center">
<span className="text-sm text-default-600 whitespace-nowrap">
{user?.name ?? "Unknown User"}
</span>
</div>
</div>
);
},
},
{
accessorKey: "date",
header: "Tanggal unggah",
cell: ({ row }) => {
return <span>{row.getValue("date")}</span>;
},
},
{
accessorKey: "quantity",
header: "Kreator",
cell: ({ row }) => {
return <span>{row.getValue("quantity")}</span>;
},
},
{
accessorKey: "amount",
header: "Sumber",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "amount",
header: "Penempatan File",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
paid: "bg-success/20 text-success",
due: "bg-warning/20 text-warning",
canceled: "bg-destructive/20 text-destructive",
};
const status = row.getValue<string>("status");
const statusStyles = statusColors[status] || "default";
return (
<Badge className={cn("rounded-full px-5", statusStyles)}>
{status}{" "}
</Badge>
);
},
},
{
accessorKey: "amount",
header: "Kurasi Konten",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "amount",
header: "Saran",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</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>
);
},
},
];

View File

@ -0,0 +1,184 @@
import { DataProps } from "./columns";
export const data: DataProps[] = [
{
id: 1,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "3/26/2022",
quantity: 13,
amount: "$1779.53",
status: "paid",
action: null,
},
{
id: 2,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "2/6/2022",
quantity: 13,
amount: "$2215.78",
status: "due",
action: null,
},
{
id: 3,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "9/6/2021",
quantity: 1,
amount: "$3183.60",
status: "due",
action: null,
},
{
id: 4,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "11/7/2021",
quantity: 13,
amount: "$2587.86",
status: "canceled",
action: null,
},
{
id: 5,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Rachel Brown",
},
date: "5/6/2022",
quantity: 12,
amount: "$3840.73",
status: "paid",
action: null,
},
{
id: 6,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Megan Taylor",
},
date: "2/14/2022",
quantity: 12,
amount: "$4764.18",
status: "canceled",
action: null,
},
{
id: 7,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Sophie Clark",
},
date: "7/30/2022",
quantity: 6,
amount: "$2875.05",
status: "paid",
action: null,
},
{
id: 8,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Natalie Martin",
},
date: "6/30/2022",
quantity: 9,
amount: "$2491.02",
status: "due",
action: null,
},
{
id: 9,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Hannah Lewis",
},
date: "8/9/2022",
quantity: 8,
amount: "$3006.95",
status: "due",
action: null,
},
{
id: 10,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Lisa White",
},
date: "8/4/2022",
quantity: 12,
amount: "$2160.32",
status: "paid",
action: null,
},
{
id: 11,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Emma Walker",
},
date: "4/5/2022",
quantity: 8,
amount: "$1272.66",
status: "paid",
action: null,
},
{
id: 12,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "8/9/2022",
quantity: 2,
amount: "$4327.86",
status: "canceled",
action: null,
},
{
id: 13,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "2/10/2022",
quantity: 11,
amount: "$3671.81",
status: "canceled",
action: null,
},
{
id: 14,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "2/10/2022",
quantity: 2,
amount: "$3401.82",
status: "paid",
action: null,
},
{
id: 15,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "5/20/2022",
quantity: 4,
amount: "$2387.49",
status: "canceled",
action: null,
},
];

View File

@ -1,6 +1,6 @@
"use client"
"use client";
import * as React from "react"
import * as React from "react";
import {
ColumnFiltersState,
SortingState,
@ -11,9 +11,9 @@ import {
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table"
import { columns } from "./columns"
import { Input } from "@/components/ui/input"
} from "@tanstack/react-table";
import { columns } from "./columns";
import { Input } from "@/components/ui/input";
import {
Table,
@ -22,20 +22,19 @@ import {
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
} from "@/components/ui/table";
import { data } from "./data"
import TablePagination from "./table-pagination"
import { useTranslations } from "next-intl"
import { data } from "./data";
import TablePagination from "./table-pagination";
const TransactionsTable= () => {
const [sorting, setSorting] = React.useState<SortingState>([])
const TableAudio = () => {
const [sorting, setSorting] = React.useState<SortingState>([]);
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
)
);
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({})
const [rowSelection, setRowSelection] = React.useState({})
React.useState<VisibilityState>({});
const [rowSelection, setRowSelection] = React.useState({});
const table = useReactTable({
data,
@ -54,21 +53,18 @@ const TransactionsTable= () => {
columnVisibility,
rowSelection,
},
})
const t = useTranslations("CrmDashboard");
});
return (
<div className="w-full">
<div className="flex items-center flex-wrap gap-2 py-4 px-5">
<div className="flex-1 text-xl font-medium text-default-900 whitespace-nowrap">
{t("latest_transactions")}
</div>
<div className="flex items-center py-4 px-5">
<div className="flex-none">
<Input
placeholder="Search..."
placeholder="Filter Status..."
value={
(table.getColumn("status")?.getFilterValue() as string) ?? ""
}
onChange={(event) =>
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
table.getColumn("status")?.setFilterValue(event.target.value)
}
className="max-w-sm "
@ -77,7 +73,7 @@ const TransactionsTable= () => {
</div>
<Table>
<TableHeader className="bg-default-200">
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
@ -103,7 +99,7 @@ const TransactionsTable= () => {
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id} className="h-[75px]">
<TableCell key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
@ -121,5 +117,5 @@ const TransactionsTable= () => {
<TablePagination table={table} />
</div>
);
}
export default TransactionsTable;
};
export default TableAudio;

View File

@ -0,0 +1,52 @@
import { Button } from '@/components/ui/button';
import { Table } from '@tanstack/react-table';
import { ChevronLeft, ChevronRight } from 'lucide-react';
interface DataTablePaginationProps {
table: Table<any>;
}
const TablePagination = ({ table }: DataTablePaginationProps) => {
return (
<div className="flex items-center justify-end py-4 px-10">
<div className="flex-1 text-sm text-muted-foreground">
{table.getFilteredSelectedRowModel().rows.length} of{" "}
{table.getFilteredRowModel().rows.length} row(s) selected.
</div>
<div className="flex items-center 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 TablePagination;

View File

@ -1,11 +0,0 @@
import { calendarEvents, categories } from "./data";
// get events
export const getEvents = async () => {
return calendarEvents;
};
// get categories
export const getCategories = async () => {
return categories;
}

View File

@ -1,7 +1,9 @@
export const metadata = {
title: "Image",
};
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Dashcode Next Js",
description: "Dashcode is a popular dashboard template.",
};
const Layout = ({ children }: { children: React.ReactNode }) => {
return <>{children}</>;
};

View File

@ -1,5 +1,78 @@
const ImagePage = async () => {
return <div></div>;
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import TableImage from "./table-image";
import { Newspaper, NewspaperIcon, UploadIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Icon } from "@iconify/react/dist/iconify.js";
const ReactTableImagePage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<Card className="py-4 px-3">
<div className="flex flex-row justify-between items-center px-5">
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="icon-park-outline:check-one" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah disetujui hari ini</p>
</div>
</div>
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="material-symbols:settings-backup-restore-rounded" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah direvisi hari ini</p>
</div>
</div>
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="healthicons:no-outline" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah ditolak hari ini</p>
</div>
</div>
</div>
</Card>
<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">
Konten Foto
</div>
<div>
<Button color="primary" className="text-white">
<UploadIcon />
Unggah Foto
</Button>
<Button color="primary" className="text-white ml-3">
<UploadIcon />
Unggah Foto Dengan AI
</Button>
</div>
</div>
</Card>
<Card>
<CardContent className="p-0">
<TableImage />
</CardContent>
</Card>
</div>
</div>
);
};
export default ImagePage;
export default ReactTableImagePage;

View File

@ -0,0 +1,180 @@
"use client";
import { ColumnDef } from "@tanstack/react-table";
import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
export type DataProps = {
id: string | number;
order: string;
customer: {
name: string;
};
date: string;
quantity: number;
amount: string;
status: "paid" | "due" | "canceled";
action: React.ReactNode;
};
export const columns: ColumnDef<DataProps>[] = [
// {
// id: "select",
// header: ({ table }) => (
// <Checkbox
// checked={
// table.getIsAllPageRowsSelected() ||
// (table.getIsSomePageRowsSelected() && "indeterminate")
// }
// onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
// aria-label="Select all"
// />
// ),
// cell: ({ row }) => (
// <div className="xl:w-16">
// <Checkbox
// checked={row.getIsSelected()}
// onCheckedChange={(value) => row.toggleSelected(!!value)}
// aria-label="Select row"
// />
// </div>
// ),
// enableSorting: false,
// enableHiding: false,
// },
{
accessorKey: "id",
header: "No",
cell: ({ row }) => <span>{row.getValue("id")}</span>,
},
{
accessorKey: "order",
header: "Judul",
cell: ({ row }) => (
<div className="w-52">
<span>{row.getValue("order")}</span>,
</div>
),
},
{
accessorKey: "customer",
header: "Kategory",
cell: ({ row }) => {
const user = row.original.customer;
return (
<div className="font-medium text-card-foreground/80">
<div className="flex gap-3 items-center">
<span className="text-sm text-default-600 whitespace-nowrap">
{user?.name ?? "Unknown User"}
</span>
</div>
</div>
);
},
},
{
accessorKey: "date",
header: "Tanggal unggah",
cell: ({ row }) => {
return <span>{row.getValue("date")}</span>;
},
},
{
accessorKey: "quantity",
header: "Kreator",
cell: ({ row }) => {
return <span>{row.getValue("quantity")}</span>;
},
},
{
accessorKey: "amount",
header: "Sumber",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "amount",
header: "Penempatan File",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
paid: "bg-success/20 text-success",
due: "bg-warning/20 text-warning",
canceled: "bg-destructive/20 text-destructive",
};
const status = row.getValue<string>("status");
const statusStyles = statusColors[status] || "default";
return (
<Badge className={cn("rounded-full px-5", statusStyles)}>
{status}{" "}
</Badge>
);
},
},
{
accessorKey: "amount",
header: "Kurasi Konten",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "amount",
header: "Saran",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</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>
);
},
},
];

View File

@ -0,0 +1,184 @@
import { DataProps } from "./columns";
export const data: DataProps[] = [
{
id: 1,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "3/26/2022",
quantity: 13,
amount: "$1779.53",
status: "paid",
action: null,
},
{
id: 2,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "2/6/2022",
quantity: 13,
amount: "$2215.78",
status: "due",
action: null,
},
{
id: 3,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "9/6/2021",
quantity: 1,
amount: "$3183.60",
status: "due",
action: null,
},
{
id: 4,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "11/7/2021",
quantity: 13,
amount: "$2587.86",
status: "canceled",
action: null,
},
{
id: 5,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Rachel Brown",
},
date: "5/6/2022",
quantity: 12,
amount: "$3840.73",
status: "paid",
action: null,
},
{
id: 6,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Megan Taylor",
},
date: "2/14/2022",
quantity: 12,
amount: "$4764.18",
status: "canceled",
action: null,
},
{
id: 7,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Sophie Clark",
},
date: "7/30/2022",
quantity: 6,
amount: "$2875.05",
status: "paid",
action: null,
},
{
id: 8,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Natalie Martin",
},
date: "6/30/2022",
quantity: 9,
amount: "$2491.02",
status: "due",
action: null,
},
{
id: 9,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Hannah Lewis",
},
date: "8/9/2022",
quantity: 8,
amount: "$3006.95",
status: "due",
action: null,
},
{
id: 10,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Lisa White",
},
date: "8/4/2022",
quantity: 12,
amount: "$2160.32",
status: "paid",
action: null,
},
{
id: 11,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Emma Walker",
},
date: "4/5/2022",
quantity: 8,
amount: "$1272.66",
status: "paid",
action: null,
},
{
id: 12,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "8/9/2022",
quantity: 2,
amount: "$4327.86",
status: "canceled",
action: null,
},
{
id: 13,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "2/10/2022",
quantity: 11,
amount: "$3671.81",
status: "canceled",
action: null,
},
{
id: 14,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "2/10/2022",
quantity: 2,
amount: "$3401.82",
status: "paid",
action: null,
},
{
id: 15,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "5/20/2022",
quantity: 4,
amount: "$2387.49",
status: "canceled",
action: null,
},
];

View File

@ -0,0 +1,121 @@
"use client";
import * as React from "react";
import {
ColumnFiltersState,
SortingState,
VisibilityState,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import { columns } from "./columns";
import { Input } from "@/components/ui/input";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { data } from "./data";
import TablePagination from "./table-pagination";
const TableImage = () => {
const [sorting, setSorting] = React.useState<SortingState>([]);
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
);
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({});
const [rowSelection, setRowSelection] = React.useState({});
const table = useReactTable({
data,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility,
onRowSelectionChange: setRowSelection,
state: {
sorting,
columnFilters,
columnVisibility,
rowSelection,
},
});
return (
<div className="w-full">
<div className="flex items-center py-4 px-5">
<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>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<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"}
>
{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} />
</div>
);
};
export default TableImage;

View File

@ -0,0 +1,52 @@
import { Button } from '@/components/ui/button';
import { Table } from '@tanstack/react-table';
import { ChevronLeft, ChevronRight } from 'lucide-react';
interface DataTablePaginationProps {
table: Table<any>;
}
const TablePagination = ({ table }: DataTablePaginationProps) => {
return (
<div className="flex items-center justify-end py-4 px-10">
<div className="flex-1 text-sm text-muted-foreground">
{table.getFilteredSelectedRowModel().rows.length} of{" "}
{table.getFilteredRowModel().rows.length} row(s) selected.
</div>
<div className="flex items-center 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 TablePagination;

View File

@ -1,11 +0,0 @@
import { calendarEvents, categories } from "./data";
// get events
export const getEvents = async () => {
return calendarEvents;
};
// get categories
export const getCategories = async () => {
return categories;
}

View File

@ -1,7 +1,9 @@
export const metadata = {
title: "Nulis",
};
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Dashcode Next Js",
description: "Dashcode is a popular dashboard template.",
};
const Layout = ({ children }: { children: React.ReactNode }) => {
return <>{children}</>;
};

View File

@ -1,5 +1,79 @@
const CalenderPage = async () => {
return <div></div>;
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import TableImage from "./table-nulis";
import { Newspaper, NewspaperIcon, UploadIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Icon } from "@iconify/react/dist/iconify.js";
import TableNulis from "./table-nulis";
const ReactTableNulisPage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<Card className="py-4 px-3">
<div className="flex flex-row justify-between items-center px-5">
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="icon-park-outline:check-one" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah disetujui hari ini</p>
</div>
</div>
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="material-symbols:settings-backup-restore-rounded" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah direvisi hari ini</p>
</div>
</div>
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="healthicons:no-outline" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah ditolak hari ini</p>
</div>
</div>
</div>
</Card>
<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">
Konten Foto
</div>
<div>
<Button color="primary" className="text-white">
<UploadIcon />
Unggah Foto
</Button>
<Button color="primary" className="text-white ml-3">
<UploadIcon />
Unggah Foto Dengan AI
</Button>
</div>
</div>
</Card>
<Card>
<CardContent className="p-0">
<TableNulis />
</CardContent>
</Card>
</div>
</div>
);
};
export default CalenderPage;
export default ReactTableNulisPage;

View File

@ -0,0 +1,180 @@
"use client";
import { ColumnDef } from "@tanstack/react-table";
import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
export type DataProps = {
id: string | number;
order: string;
customer: {
name: string;
};
date: string;
quantity: number;
amount: string;
status: "paid" | "due" | "canceled";
action: React.ReactNode;
};
export const columns: ColumnDef<DataProps>[] = [
// {
// id: "select",
// header: ({ table }) => (
// <Checkbox
// checked={
// table.getIsAllPageRowsSelected() ||
// (table.getIsSomePageRowsSelected() && "indeterminate")
// }
// onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
// aria-label="Select all"
// />
// ),
// cell: ({ row }) => (
// <div className="xl:w-16">
// <Checkbox
// checked={row.getIsSelected()}
// onCheckedChange={(value) => row.toggleSelected(!!value)}
// aria-label="Select row"
// />
// </div>
// ),
// enableSorting: false,
// enableHiding: false,
// },
{
accessorKey: "id",
header: "No",
cell: ({ row }) => <span>{row.getValue("id")}</span>,
},
{
accessorKey: "order",
header: "Judul",
cell: ({ row }) => (
<div className="w-52">
<span>{row.getValue("order")}</span>,
</div>
),
},
{
accessorKey: "customer",
header: "Kategory",
cell: ({ row }) => {
const user = row.original.customer;
return (
<div className="font-medium text-card-foreground/80">
<div className="flex gap-3 items-center">
<span className="text-sm text-default-600 whitespace-nowrap">
{user?.name ?? "Unknown User"}
</span>
</div>
</div>
);
},
},
{
accessorKey: "date",
header: "Tanggal unggah",
cell: ({ row }) => {
return <span>{row.getValue("date")}</span>;
},
},
{
accessorKey: "quantity",
header: "Kreator",
cell: ({ row }) => {
return <span>{row.getValue("quantity")}</span>;
},
},
{
accessorKey: "amount",
header: "Sumber",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "amount",
header: "Penempatan File",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
paid: "bg-success/20 text-success",
due: "bg-warning/20 text-warning",
canceled: "bg-destructive/20 text-destructive",
};
const status = row.getValue<string>("status");
const statusStyles = statusColors[status] || "default";
return (
<Badge className={cn("rounded-full px-5", statusStyles)}>
{status}{" "}
</Badge>
);
},
},
{
accessorKey: "amount",
header: "Kurasi Konten",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "amount",
header: "Saran",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</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>
);
},
},
];

View File

@ -0,0 +1,184 @@
import { DataProps } from "./columns";
export const data: DataProps[] = [
{
id: 1,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "3/26/2022",
quantity: 13,
amount: "$1779.53",
status: "paid",
action: null,
},
{
id: 2,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "2/6/2022",
quantity: 13,
amount: "$2215.78",
status: "due",
action: null,
},
{
id: 3,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "9/6/2021",
quantity: 1,
amount: "$3183.60",
status: "due",
action: null,
},
{
id: 4,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "11/7/2021",
quantity: 13,
amount: "$2587.86",
status: "canceled",
action: null,
},
{
id: 5,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Rachel Brown",
},
date: "5/6/2022",
quantity: 12,
amount: "$3840.73",
status: "paid",
action: null,
},
{
id: 6,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Megan Taylor",
},
date: "2/14/2022",
quantity: 12,
amount: "$4764.18",
status: "canceled",
action: null,
},
{
id: 7,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Sophie Clark",
},
date: "7/30/2022",
quantity: 6,
amount: "$2875.05",
status: "paid",
action: null,
},
{
id: 8,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Natalie Martin",
},
date: "6/30/2022",
quantity: 9,
amount: "$2491.02",
status: "due",
action: null,
},
{
id: 9,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Hannah Lewis",
},
date: "8/9/2022",
quantity: 8,
amount: "$3006.95",
status: "due",
action: null,
},
{
id: 10,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Lisa White",
},
date: "8/4/2022",
quantity: 12,
amount: "$2160.32",
status: "paid",
action: null,
},
{
id: 11,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Emma Walker",
},
date: "4/5/2022",
quantity: 8,
amount: "$1272.66",
status: "paid",
action: null,
},
{
id: 12,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "8/9/2022",
quantity: 2,
amount: "$4327.86",
status: "canceled",
action: null,
},
{
id: 13,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "2/10/2022",
quantity: 11,
amount: "$3671.81",
status: "canceled",
action: null,
},
{
id: 14,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "2/10/2022",
quantity: 2,
amount: "$3401.82",
status: "paid",
action: null,
},
{
id: 15,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "5/20/2022",
quantity: 4,
amount: "$2387.49",
status: "canceled",
action: null,
},
];

View File

@ -0,0 +1,121 @@
"use client";
import * as React from "react";
import {
ColumnFiltersState,
SortingState,
VisibilityState,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import { columns } from "./columns";
import { Input } from "@/components/ui/input";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { data } from "./data";
import TablePagination from "./table-pagination";
const TableNulis = () => {
const [sorting, setSorting] = React.useState<SortingState>([]);
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
);
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({});
const [rowSelection, setRowSelection] = React.useState({});
const table = useReactTable({
data,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility,
onRowSelectionChange: setRowSelection,
state: {
sorting,
columnFilters,
columnVisibility,
rowSelection,
},
});
return (
<div className="w-full">
<div className="flex items-center py-4 px-5">
<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>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<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"}
>
{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} />
</div>
);
};
export default TableNulis;

View File

@ -0,0 +1,52 @@
import { Button } from '@/components/ui/button';
import { Table } from '@tanstack/react-table';
import { ChevronLeft, ChevronRight } from 'lucide-react';
interface DataTablePaginationProps {
table: Table<any>;
}
const TablePagination = ({ table }: DataTablePaginationProps) => {
return (
<div className="flex items-center justify-end py-4 px-10">
<div className="flex-1 text-sm text-muted-foreground">
{table.getFilteredSelectedRowModel().rows.length} of{" "}
{table.getFilteredRowModel().rows.length} row(s) selected.
</div>
<div className="flex items-center 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 TablePagination;

View File

@ -1,7 +1,9 @@
export const metadata = {
title: "Spit",
};
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Dashcode Next Js",
description: "Dashcode is a popular dashboard template.",
};
const Layout = ({ children }: { children: React.ReactNode }) => {
return <>{children}</>;
};

View File

@ -1,5 +1,42 @@
const CalenderPage = async () => {
return <div></div>;
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import TableImage from "./table-spit";
import { Newspaper, NewspaperIcon, UploadIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Icon } from "@iconify/react/dist/iconify.js";
import TableSPIT from "./table-spit";
const ReactTableSPITPage = () => {
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">
Konten SPIT
</div>
{/* <div>
<Button color="primary" className="text-white">
<UploadIcon />
Unggah Foto
</Button>
<Button color="primary" className="text-white ml-3">
<UploadIcon />
Unggah Foto Dengan AI
</Button>
</div> */}
</div>
</Card>
<Card>
<CardContent className="p-0">
<TableSPIT />
</CardContent>
</Card>
</div>
</div>
);
};
export default CalenderPage;
export default ReactTableSPITPage;

View File

@ -0,0 +1,180 @@
"use client";
import { ColumnDef } from "@tanstack/react-table";
import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
export type DataProps = {
id: string | number;
order: string;
customer: {
name: string;
};
date: string;
quantity: number;
amount: string;
status: "paid" | "due" | "canceled";
action: React.ReactNode;
};
export const columns: ColumnDef<DataProps>[] = [
// {
// id: "select",
// header: ({ table }) => (
// <Checkbox
// checked={
// table.getIsAllPageRowsSelected() ||
// (table.getIsSomePageRowsSelected() && "indeterminate")
// }
// onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
// aria-label="Select all"
// />
// ),
// cell: ({ row }) => (
// <div className="xl:w-16">
// <Checkbox
// checked={row.getIsSelected()}
// onCheckedChange={(value) => row.toggleSelected(!!value)}
// aria-label="Select row"
// />
// </div>
// ),
// enableSorting: false,
// enableHiding: false,
// },
{
accessorKey: "id",
header: "No",
cell: ({ row }) => <span>{row.getValue("id")}</span>,
},
{
accessorKey: "order",
header: "Judul",
cell: ({ row }) => (
<div className="w-52">
<span>{row.getValue("order")}</span>,
</div>
),
},
{
accessorKey: "customer",
header: "Kategory",
cell: ({ row }) => {
const user = row.original.customer;
return (
<div className="font-medium text-card-foreground/80">
<div className="flex gap-3 items-center">
<span className="text-sm text-default-600 whitespace-nowrap">
{user?.name ?? "Unknown User"}
</span>
</div>
</div>
);
},
},
{
accessorKey: "date",
header: "Tanggal unggah",
cell: ({ row }) => {
return <span>{row.getValue("date")}</span>;
},
},
{
accessorKey: "quantity",
header: "Kreator",
cell: ({ row }) => {
return <span>{row.getValue("quantity")}</span>;
},
},
{
accessorKey: "amount",
header: "Sumber",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "amount",
header: "Penempatan File",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
paid: "bg-success/20 text-success",
due: "bg-warning/20 text-warning",
canceled: "bg-destructive/20 text-destructive",
};
const status = row.getValue<string>("status");
const statusStyles = statusColors[status] || "default";
return (
<Badge className={cn("rounded-full px-5", statusStyles)}>
{status}{" "}
</Badge>
);
},
},
{
accessorKey: "amount",
header: "Kurasi Konten",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "amount",
header: "Saran",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</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>
);
},
},
];

View File

@ -0,0 +1,184 @@
import { DataProps } from "./columns";
export const data: DataProps[] = [
{
id: 1,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "3/26/2022",
quantity: 13,
amount: "$1779.53",
status: "paid",
action: null,
},
{
id: 2,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "2/6/2022",
quantity: 13,
amount: "$2215.78",
status: "due",
action: null,
},
{
id: 3,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "9/6/2021",
quantity: 1,
amount: "$3183.60",
status: "due",
action: null,
},
{
id: 4,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "11/7/2021",
quantity: 13,
amount: "$2587.86",
status: "canceled",
action: null,
},
{
id: 5,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Rachel Brown",
},
date: "5/6/2022",
quantity: 12,
amount: "$3840.73",
status: "paid",
action: null,
},
{
id: 6,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Megan Taylor",
},
date: "2/14/2022",
quantity: 12,
amount: "$4764.18",
status: "canceled",
action: null,
},
{
id: 7,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Sophie Clark",
},
date: "7/30/2022",
quantity: 6,
amount: "$2875.05",
status: "paid",
action: null,
},
{
id: 8,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Natalie Martin",
},
date: "6/30/2022",
quantity: 9,
amount: "$2491.02",
status: "due",
action: null,
},
{
id: 9,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Hannah Lewis",
},
date: "8/9/2022",
quantity: 8,
amount: "$3006.95",
status: "due",
action: null,
},
{
id: 10,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Lisa White",
},
date: "8/4/2022",
quantity: 12,
amount: "$2160.32",
status: "paid",
action: null,
},
{
id: 11,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Emma Walker",
},
date: "4/5/2022",
quantity: 8,
amount: "$1272.66",
status: "paid",
action: null,
},
{
id: 12,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "8/9/2022",
quantity: 2,
amount: "$4327.86",
status: "canceled",
action: null,
},
{
id: 13,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "2/10/2022",
quantity: 11,
amount: "$3671.81",
status: "canceled",
action: null,
},
{
id: 14,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "2/10/2022",
quantity: 2,
amount: "$3401.82",
status: "paid",
action: null,
},
{
id: 15,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "5/20/2022",
quantity: 4,
amount: "$2387.49",
status: "canceled",
action: null,
},
];

View File

@ -0,0 +1,121 @@
"use client";
import * as React from "react";
import {
ColumnFiltersState,
SortingState,
VisibilityState,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import { columns } from "./columns";
import { Input } from "@/components/ui/input";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { data } from "./data";
import TablePagination from "./table-pagination";
const TableSPIT = () => {
const [sorting, setSorting] = React.useState<SortingState>([]);
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
);
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({});
const [rowSelection, setRowSelection] = React.useState({});
const table = useReactTable({
data,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility,
onRowSelectionChange: setRowSelection,
state: {
sorting,
columnFilters,
columnVisibility,
rowSelection,
},
});
return (
<div className="w-full">
<div className="flex items-center py-4 px-5">
<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>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<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"}
>
{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} />
</div>
);
};
export default TableSPIT;

View File

@ -0,0 +1,52 @@
import { Button } from '@/components/ui/button';
import { Table } from '@tanstack/react-table';
import { ChevronLeft, ChevronRight } from 'lucide-react';
interface DataTablePaginationProps {
table: Table<any>;
}
const TablePagination = ({ table }: DataTablePaginationProps) => {
return (
<div className="flex items-center justify-end py-4 px-10">
<div className="flex-1 text-sm text-muted-foreground">
{table.getFilteredSelectedRowModel().rows.length} of{" "}
{table.getFilteredRowModel().rows.length} row(s) selected.
</div>
<div className="flex items-center 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 TablePagination;

View File

@ -1,7 +1,9 @@
export const metadata = {
title: "Teks",
};
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Dashcode Next Js",
description: "Dashcode is a popular dashboard template.",
};
const Layout = ({ children }: { children: React.ReactNode }) => {
return <>{children}</>;
};

View File

@ -1,5 +1,79 @@
const TeksPage = async () => {
return <div></div>;
"use client";
import { Card, CardContent } from "@/components/ui/card";
import SiteBreadcrumb from "@/components/site-breadcrumb";
import TableImage from "./table-teks";
import { Newspaper, NewspaperIcon, UploadIcon } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Icon } from "@iconify/react/dist/iconify.js";
import TableTeks from "./table-teks";
const ReactTableTeksPage = () => {
return (
<div>
<SiteBreadcrumb />
<div className="space-y-4">
<Card className="py-4 px-3">
<div className="flex flex-row justify-between items-center px-5">
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="icon-park-outline:check-one" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah disetujui hari ini</p>
</div>
</div>
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="material-symbols:settings-backup-restore-rounded" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah direvisi hari ini</p>
</div>
</div>
<div className="flex flex-row items-center text-xl font-medium text-default-900 gap-2">
<div>
<Icon icon="healthicons:no-outline" />
</div>
<div>
<p>
0 <span className="text-red-500">Rata - rata :0</span>
</p>
<p className="text-sm">Hasil Unggah ditolak hari ini</p>
</div>
</div>
</div>
</Card>
<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">
Konten Teks
</div>
<div>
<Button color="primary" className="text-white">
<UploadIcon />
Unggah Teks
</Button>
<Button color="primary" className="text-white ml-3">
<UploadIcon />
Unggah Teks Dengan AI
</Button>
</div>
</div>
</Card>
<Card>
<CardContent className="p-0">
<TableTeks />
</CardContent>
</Card>
</div>
</div>
);
};
export default TeksPage;
export default ReactTableTeksPage;

View File

@ -0,0 +1,180 @@
"use client";
import { ColumnDef } from "@tanstack/react-table";
import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
export type DataProps = {
id: string | number;
order: string;
customer: {
name: string;
};
date: string;
quantity: number;
amount: string;
status: "paid" | "due" | "canceled";
action: React.ReactNode;
};
export const columns: ColumnDef<DataProps>[] = [
// {
// id: "select",
// header: ({ table }) => (
// <Checkbox
// checked={
// table.getIsAllPageRowsSelected() ||
// (table.getIsSomePageRowsSelected() && "indeterminate")
// }
// onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
// aria-label="Select all"
// />
// ),
// cell: ({ row }) => (
// <div className="xl:w-16">
// <Checkbox
// checked={row.getIsSelected()}
// onCheckedChange={(value) => row.toggleSelected(!!value)}
// aria-label="Select row"
// />
// </div>
// ),
// enableSorting: false,
// enableHiding: false,
// },
{
accessorKey: "id",
header: "No",
cell: ({ row }) => <span>{row.getValue("id")}</span>,
},
{
accessorKey: "order",
header: "Judul",
cell: ({ row }) => (
<div className="w-52">
<span>{row.getValue("order")}</span>,
</div>
),
},
{
accessorKey: "customer",
header: "Kategory",
cell: ({ row }) => {
const user = row.original.customer;
return (
<div className="font-medium text-card-foreground/80">
<div className="flex gap-3 items-center">
<span className="text-sm text-default-600 whitespace-nowrap">
{user?.name ?? "Unknown User"}
</span>
</div>
</div>
);
},
},
{
accessorKey: "date",
header: "Tanggal unggah",
cell: ({ row }) => {
return <span>{row.getValue("date")}</span>;
},
},
{
accessorKey: "quantity",
header: "Kreator",
cell: ({ row }) => {
return <span>{row.getValue("quantity")}</span>;
},
},
{
accessorKey: "amount",
header: "Sumber",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "amount",
header: "Penempatan File",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
paid: "bg-success/20 text-success",
due: "bg-warning/20 text-warning",
canceled: "bg-destructive/20 text-destructive",
};
const status = row.getValue<string>("status");
const statusStyles = statusColors[status] || "default";
return (
<Badge className={cn("rounded-full px-5", statusStyles)}>
{status}{" "}
</Badge>
);
},
},
{
accessorKey: "amount",
header: "Kurasi Konten",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</span>;
},
},
{
accessorKey: "amount",
header: "Saran",
cell: ({ row }) => {
return <span>{row.getValue("amount")}</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>
);
},
},
];

View File

@ -0,0 +1,184 @@
import { DataProps } from "./columns";
export const data: DataProps[] = [
{
id: 1,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "3/26/2022",
quantity: 13,
amount: "$1779.53",
status: "paid",
action: null,
},
{
id: 2,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "2/6/2022",
quantity: 13,
amount: "$2215.78",
status: "due",
action: null,
},
{
id: 3,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "9/6/2021",
quantity: 1,
amount: "$3183.60",
status: "due",
action: null,
},
{
id: 4,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Liputan Kegiatan",
},
date: "11/7/2021",
quantity: 13,
amount: "$2587.86",
status: "canceled",
action: null,
},
{
id: 5,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Rachel Brown",
},
date: "5/6/2022",
quantity: 12,
amount: "$3840.73",
status: "paid",
action: null,
},
{
id: 6,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Megan Taylor",
},
date: "2/14/2022",
quantity: 12,
amount: "$4764.18",
status: "canceled",
action: null,
},
{
id: 7,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Sophie Clark",
},
date: "7/30/2022",
quantity: 6,
amount: "$2875.05",
status: "paid",
action: null,
},
{
id: 8,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Natalie Martin",
},
date: "6/30/2022",
quantity: 9,
amount: "$2491.02",
status: "due",
action: null,
},
{
id: 9,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Hannah Lewis",
},
date: "8/9/2022",
quantity: 8,
amount: "$3006.95",
status: "due",
action: null,
},
{
id: 10,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Lisa White",
},
date: "8/4/2022",
quantity: 12,
amount: "$2160.32",
status: "paid",
action: null,
},
{
id: 11,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Emma Walker",
},
date: "4/5/2022",
quantity: 8,
amount: "$1272.66",
status: "paid",
action: null,
},
{
id: 12,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "8/9/2022",
quantity: 2,
amount: "$4327.86",
status: "canceled",
action: null,
},
{
id: 13,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "2/10/2022",
quantity: 11,
amount: "$3671.81",
status: "canceled",
action: null,
},
{
id: 14,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "2/10/2022",
quantity: 2,
amount: "$3401.82",
status: "paid",
action: null,
},
{
id: 15,
order: "Pertemuan PPID Satker Mabes Polri Langkah Strate",
customer: {
name: "Jenny Wilson",
},
date: "5/20/2022",
quantity: 4,
amount: "$2387.49",
status: "canceled",
action: null,
},
];

View File

@ -0,0 +1,121 @@
"use client";
import * as React from "react";
import {
ColumnFiltersState,
SortingState,
VisibilityState,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import { columns } from "./columns";
import { Input } from "@/components/ui/input";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { data } from "./data";
import TablePagination from "./table-pagination";
const TableTeks = () => {
const [sorting, setSorting] = React.useState<SortingState>([]);
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
);
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({});
const [rowSelection, setRowSelection] = React.useState({});
const table = useReactTable({
data,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility,
onRowSelectionChange: setRowSelection,
state: {
sorting,
columnFilters,
columnVisibility,
rowSelection,
},
});
return (
<div className="w-full">
<div className="flex items-center py-4 px-5">
<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>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<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"}
>
{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} />
</div>
);
};
export default TableTeks;

View File

@ -0,0 +1,52 @@
import { Button } from '@/components/ui/button';
import { Table } from '@tanstack/react-table';
import { ChevronLeft, ChevronRight } from 'lucide-react';
interface DataTablePaginationProps {
table: Table<any>;
}
const TablePagination = ({ table }: DataTablePaginationProps) => {
return (
<div className="flex items-center justify-end py-4 px-10">
<div className="flex-1 text-sm text-muted-foreground">
{table.getFilteredSelectedRowModel().rows.length} of{" "}
{table.getFilteredRowModel().rows.length} row(s) selected.
</div>
<div className="flex items-center 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 TablePagination;

View File

@ -1,6 +1,6 @@
"use client"
"use client";
import * as React from "react"
import * as React from "react";
import {
ColumnDef,
ColumnFiltersState,
@ -13,9 +13,9 @@ import {
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table"
import { Button } from "@/components/ui/button"
import { data } from "./data"
} from "@tanstack/react-table";
import { Button } from "@/components/ui/button";
import { data } from "./data";
import {
Table,
TableBody,
@ -23,24 +23,40 @@ import {
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { ChevronLeft, ChevronRight, TrendingDown, TrendingUp } from "lucide-react"
} 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;
views: number;
revenue: string;
sales: number;
status: string;
up: boolean;
}
};
export const columns: ColumnDef<CompanyData>[] = [
{
accessorKey: "company",
header: "Company",
header: "Judul",
cell: ({ row }) => (
<div className="flex items-center gap-5">
<div className="flex-none">
@ -64,51 +80,91 @@ export const columns: ColumnDef<CompanyData>[] = [
},
{
accessorKey: "category",
header: "Category",
header: "Tanggal Unggah",
cell: ({ row }) => (
<span className="whitespace-nowrap">{row.getValue("category")}</span>
),
},
{
accessorKey: "sales",
header: "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" />
}
{row?.original.up ? (
<TrendingUp className="text-success w-4 h-4" />
) : (
<TrendingDown className="text-destructive w-4 h-4" />
)}
</div>
)
),
},
{
accessorKey: "views",
header: "Views",
cell: ({ row }) => (
<span>{row.getValue("views")}</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>
);
},
},
{
accessorKey: "revenue",
header: "Revenue",
cell: ({ row }) => (
<span>{row.getValue("revenue")}</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 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 [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,
@ -127,9 +183,9 @@ const CompanyTable = () => {
columnFilters,
columnVisibility,
rowSelection,
pagination
pagination,
},
})
});
return (
<div className="w-full overflow-x-auto">
@ -139,10 +195,12 @@ const CompanyTable = () => {
<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()
)}
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
))}
</TableRow>
@ -158,20 +216,14 @@ const CompanyTable = () => {
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
<TableCell colSpan={columns.length} className="h-24 text-center">
No results.
</TableCell>
</TableRow>
@ -184,9 +236,9 @@ const CompanyTable = () => {
size="icon"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
className='w-8 h-8'
className="w-8 h-8"
>
<ChevronLeft className='w-4 h-4' />
<ChevronLeft className="w-4 h-4" />
</Button>
{table.getPageOptions().map((page, pageIndex) => (
<Button
@ -194,25 +246,27 @@ const CompanyTable = () => {
onClick={() => table.setPageIndex(pageIndex)}
size="icon"
className="w-8 h-8"
variant={table.getState().pagination.pageIndex === pageIndex ? 'default' : 'outline'}
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'
className="w-8 h-8"
>
<ChevronRight className='w-4 h-4' />
<ChevronRight className="w-4 h-4" />
</Button>
</div>
</div>
)
}
);
};
export default CompanyTable;

View File

@ -1,10 +1,8 @@
export const data = [
{
company: "/images/users/user-1.jpg",
category: "Ornamental Railings",
views: 343,
status: "paid",
revenue: "$231.26",
sales: 95,
up: false,
@ -12,7 +10,7 @@ export const data = [
{
company: "/images/users/user-2.jpg",
category: "Asphalt Paving",
views: 315,
status: "due",
revenue: "$432.81",
sales: 197,
up: false,
@ -20,7 +18,7 @@ export const data = [
{
company: "/images/users/user-3.jpg",
category: "Framing (Steel)",
views: 329,
status: "due",
revenue: "$437.65",
sales: 137,
up: true,
@ -28,7 +26,7 @@ export const data = [
{
company: "/images/users/user-4.jpg",
category: "Structural and Misc Steel (Fabrication)",
views: 336,
status: "canceled",
revenue: "$387.55",
sales: 101,
up: true,
@ -36,7 +34,7 @@ export const data = [
{
company: "/images/users/user-5.jpg",
category: "Wall Protection",
views: 375,
status: "canceled",
revenue: "$489.80",
sales: 99,
up: false,
@ -44,7 +42,7 @@ export const data = [
{
company: "/images/users/user-6.jpg",
category: "Marlite Panels (FED)",
views: 490,
status: "canceled",
revenue: "$421.45",
sales: 101,
up: true,
@ -52,7 +50,7 @@ export const data = [
{
company: "/images/users/user-1.jpg",
category: "Epoxy Flooring",
views: 433,
status: "canceled",
revenue: "$207.61",
sales: 197,
up: false,
@ -60,7 +58,7 @@ export const data = [
{
company: "/images/users/user-2.jpg",
category: "Epoxy Flooring",
views: 499,
status: "paid",
revenue: "$392.86",
sales: 91,
up: false,
@ -68,7 +66,7 @@ export const data = [
{
company: "/images/users/user-3.jpg",
category: "Marlite Panels (FED)",
views: 441,
status: "paid",
revenue: "$162.87",
sales: 115,
up: false,
@ -76,7 +74,7 @@ export const data = [
{
company: "/images/users/user-4.jpg",
category: "RF Shielding",
views: 415,
status: "paid",
revenue: "$268.58",
sales: 128,
up: false,
@ -84,7 +82,7 @@ export const data = [
{
company: "/images/users/user-5.jpg",
category: "Roofing (Metal)",
views: 303,
status: "paid",
revenue: "$369.19",
sales: 179,
up: false,
@ -92,7 +90,7 @@ export const data = [
{
company: "/images/users/user-6.jpg",
category: "RF Shielding",
views: 415,
status: "paid",
revenue: "$420.87",
sales: 148,
up: false,
@ -100,213 +98,9 @@ export const data = [
{
company: "/images/users/user-1.jpg",
category: "Curb & Gutter",
views: 493,
status: "paid",
revenue: "$420.26",
sales: 152,
up: false,
},
{
company: "/images/users/user-2.jpg",
category: "Structural & Misc Steel Erection",
views: 498,
revenue: "$228.41",
sales: 151,
up: false,
},
{
company: "/images/users/user-3.jpg",
category: "Retaining Wall and Brick Pavers",
views: 465,
revenue: "$140.83",
sales: 71,
up: false,
},
{
company: "/images/users/user-4.jpg",
category: "Sitework & Site Utilities",
views: 468,
revenue: "$475.63",
sales: 114,
up: false,
},
{
company: "/images/users/user-5.jpg",
category: "Framing (Steel)",
views: 357,
revenue: "$415.37",
sales: 163,
up: false,
},
{
company: "/images/users/user-6.jpg",
category: "Waterproofing & Caulking",
views: 487,
revenue: "$436.53",
sales: 170,
up: false,
},
{
company: "/images/users/user-1.jpg",
category: "Site Furnishings",
views: 357,
revenue: "$147.36",
sales: 71,
up: false,
},
{
company: "/images/users/user-2.jpg",
category: "Casework",
views: 465,
revenue: "$121.67",
sales: 78,
up: false,
},
{
company: "/images/users/user-3.jpg",
category: "Ornamental Railings",
views: 438,
revenue: "$213.25",
sales: 155,
up: false,
},
{
company: "/images/users/user-4.jpg",
category: "Waterproofing & Caulking",
views: 461,
revenue: "$186.48",
sales: 137,
up: false,
},
{
company: "/images/users/user-5.jpg",
category: "Masonry",
views: 423,
revenue: "$130.97",
sales: 178,
up: false,
},
{
company: "/images/users/user-6.jpg",
category: "Curb & Gutter",
views: 339,
revenue: "$255.69",
sales: 101,
up: false,
},
{
company: "/images/users/user-1.jpg",
category: "HVAC",
views: 361,
revenue: "$484.64",
sales: 175,
up: true,
},
{
company: "/images/users/user-2.jpg",
category: "Exterior Signage",
views: 353,
revenue: "$485.51",
sales: 176,
up: true,
},
{
company: "/images/users/user-3.jpg",
category: "Fire Protection",
views: 364,
revenue: "$449.45",
sales: 136,
up: true,
},
{
company: "/images/users/user-4.jpg",
category: "Rebar & Wire Mesh Install",
views: 493,
revenue: "$309.61",
sales: 163,
up: true,
},
{
company: "/images/users/user-5.jpg",
category: "Temp Fencing, Decorative Fencing and Gates",
views: 393,
revenue: "$372.45",
sales: 180,
up: true,
},
{
company: "/images/users/user-6.jpg",
category: "Fire Protection",
views: 441,
revenue: "$470.34",
sales: 104,
up: false,
},
];
export const activity = [
{
id: 1,
img: "/images/users/user-1.jpg",
description: "Finance KPI Mobile app launch preparation meeting.",
time: "1 hour",
},
{
id: 2,
img: "/images/users/user-2.jpg",
description: "Design review meeting.",
time: "2 hours",
},
{
id: 3,
img: "/images/users/user-3.jpg",
description: "Project kick-off meeting.",
time: "3 hours",
},
{
id: 4,
img: "/images/users/user-4.jpg",
description: "Weekly sync-up meeting.",
time: "4 hours",
},
{
id: 5,
img: "/images/users/user-5.jpg",
description: "Client presentation meeting.",
time: "5 hours",
},
{
id: 6,
img: "/images/users/user-6.jpg",
description: "Product roadmap discussion.",
time: "6 hours",
},
{
id: 7,
img: "/images/users/user-1.jpg",
description: "Team retrospective meeting.",
time: "7 hours",
},
{
id: 8,
img: "/images/users/user-2.jpg",
description: "Sprint planning meeting.",
time: "8 hours",
},
{
id: 9,
img: "/images/users/user-3.jpg",
description: "Code review session.",
time: "9 hours",
},
{
id: 10,
img: "/images/users/user-4.jpg",
description: "Stakeholder alignment meeting.",
time: "10 hours",
},
];

View File

@ -1,31 +1,36 @@
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import {activity} from "./data"
"use client";
import {
DockIcon,
ImageIcon,
MicIcon,
PaperclipIcon,
TextIcon,
VideoIcon,
YoutubeIcon,
} from "lucide-react";
const RecentActivity = () => {
return (
<ul className=" space-y-3 h-full ">
{activity.map((item) => (
<li
className="flex items-center gap-3 border-b border-default-100 dark:border-default-300 last:border-b-0 pb-3 last:pb-0"
key={item.id}
>
<Avatar className="w-8 h-8">
<AvatarImage src={item.img} alt="next-avater" />
<AvatarFallback> SA </AvatarFallback>
</Avatar>
<div className="flex-1 text-start overflow-hidden text-ellipsis whitespace-nowrap max-w-[63%]">
<div className="text-sm text-default-600 overflow-hidden text-ellipsis whitespace-nowrap">
{item.description}
</div>
</div>
<div className="flex-none ">
<div className="text-sm font-light text-default-400 dark:text-default-600">
{item.time}
</div>
</div>
</li>
))}
</ul>
<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>
</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>
</div>
<div className="flex flex-row items-center gap-3">
<DockIcon size={40} className="text-blue-700" />
<p className="text-2xl">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>
</div>
</div>
);
};
export default RecentActivity;
export default RecentActivity;

View File

@ -15,44 +15,23 @@ const DashboardPage = () => {
return (
<div>
<div className="grid grid-cols-12 items-center gap-5 mb-5">
<div className="2xl:col-span-3 lg:col-span-4 col-span-12">
<WelcomeBlock>
<div className="max-w-[180px] relative z-10">
<div className="text-xl font-medium text-default-900 dark:text-default-100 mb-2">
{t("widget_title")}
</div>
<p className="text-sm text-default-800 dark:text-default-100">
{t("widget_desc")}
</p>
</div>
<BlockBadge className="end-3">{t("widget_badge")}</BlockBadge>
<Image
src="/images/all-img/widget-bg-1.png"
width={400}
height={150}
priority
alt="Description of the image"
className="absolute top-0 start-0 w-full h-full object-cover rounded-md"
/>
</WelcomeBlock>
</div>
<div className="2xl:col-span-9 lg:col-span-8 col-span-12">
<div className="2xl:col-span-12 lg:col-span-12 col-span-12">
<Card>
<CardContent className="p-4">
<div className="grid md:grid-cols-3 gap-4">
<StatisticsBlock
title={t("revenue_chart_title")}
title={"Hasil unggah disetujui hari ini"}
total="3,564"
className="bg-info/10 border-none shadow-none"
/>
<StatisticsBlock
title={t("sold_chart_title")}
title={"Hasil unggah direvisi hari ini"}
total="564"
className="bg-warning/10 border-none shadow-none"
chartColor="#FB8F65"
/>
<StatisticsBlock
title={t("growth_chart_title")}
title={"Hasil unggah ditolak hari ini"}
total="+5.0%"
className="bg-primary/10 border-none shadow-none"
chartColor="#2563eb"
@ -63,44 +42,11 @@ const DashboardPage = () => {
</div>
</div>
<div className="grid grid-cols-12 gap-5">
<div className="lg:col-span-8 col-span-12">
<Card>
<CardContent className="p-4">
<RevinueBarChart />
</CardContent>
</Card>
</div>
<div className="lg:col-span-4 col-span-12">
<Card>
<CardHeader className="flex flex-row items-center">
<CardTitle className="flex-1">
{t("overview_circle_chart_title")}
</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<OverviewChart />
</CardContent>
</Card>
</div>
<div className="lg:col-span-8 col-span-12">
<Card>
<CardHeader className="flex flex-row items-center">
<CardTitle className="flex-1">
{t("company_table_title")}
</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent className="p-0">
<CompanyTable />
</CardContent>
</Card>
</div>
<div className="lg:col-span-4 col-span-12">
<Card>
<CardHeader className="flex flex-row items-center">
<CardTitle className="flex-1">
{t("recent_activity_table_title")}
{"Total Produksi Konten"}
</CardTitle>
<DashboardDropdown />
</CardHeader>
@ -110,49 +56,13 @@ const DashboardPage = () => {
</Card>
</div>
<div className="lg:col-span-8 col-span-12">
<MostSales />
</div>
<div className="lg:col-span-4 col-span-12">
<Card>
<CardHeader className="flex flex-row items-center">
<CardTitle className="flex-1">
{t("overview_circle_chart_title")}
</CardTitle>
<CardTitle className="flex-1">{"Table"}</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<OverviewRadialChart />
<div className="bg-default-50 rounded p-4 mt-8 flex justify-between flex-wrap">
<div className="space-y-1">
<h4 className="text-default-600 text-xs font-normal">
{t("invested_amount")}
</h4>
<div className="text-sm font-medium text-default-900">
$8264.35
</div>
<div className="text-default-500 text-xs font-normal">
+0.001.23 (0.2%)
</div>
</div>
<div className="space-y-1">
<h4 className="text-default-600 text-xs font-normal">
{t("invested_amount")}
</h4>
<div className="text-sm font-medium text-default-900">
$8264.35
</div>
</div>
<div className="space-y-1">
<h4 className="text-default-600 text-xs font-normal">
{t("invested_amount")}
</h4>
<div className="text-sm font-medium text-default-900">
$8264.35
</div>
</div>
</div>
<CardContent className="p-0">
<CompanyTable />
</CardContent>
</Card>
</div>

View File

@ -1,109 +0,0 @@
"use client";
import dynamic from "next/dynamic";
const Chart = dynamic(() => import("react-apexcharts"), { ssr: false });
import { colors } from "@/lib/colors";
import { useTheme } from "next-themes";
import {
getGridConfig,
getYAxisConfig,
} from "@/lib/appex-chart-options";
interface AccountChartProps {
height?: number;
series?: {
data: number[]
}[];
chartType?: "line" | "area" | "bar";
chartColor?: keyof typeof colors;
}
const AccountChart = (
{
height = 300,
series = [
{
data: [31, 40, 28, 51, 42, 109, 100]
}
],
chartType = "line",
chartColor = "warning",
}: AccountChartProps) => {
const { theme: mode } = useTheme();
const options: any = {
chart: {
toolbar: {
show: false,
}
},
dataLabels: {
enabled: false,
},
stroke: {
curve: "smooth",
width: 2,
},
colors: [colors[chartColor]],
grid: getGridConfig(),
tooltip: {
theme: mode === "dark" ? "dark" : "light",
},
yaxis: getYAxisConfig(
mode === 'light' ? colors["default-600"] : colors["default-300"]
),
xaxis: {
type: "datetime",
categories: [
"2018-09-19T00:00:00.000Z",
"2018-09-19T01:30:00.000Z",
"2018-09-19T02:30:00.000Z",
"2018-09-19T03:30:00.000Z",
"2018-09-19T04:30:00.000Z",
"2018-09-19T05:30:00.000Z",
"2018-09-19T06:30:00.000Z",
],
labels: {
style: {
colors: mode === 'light' ? colors["default-600"] : colors["default-300"],
fontFamily: "Inter",
},
},
axisBorder: {
show: false,
},
axisTicks: {
show: false,
}
},
markers: {
size: 4,
colors: [colors[chartColor]],
strokeColors: colors[chartColor],
strokeWidth: 2,
shape: "circle",
radius: 2,
hover: {
sizeOffset: 1,
},
},
padding: {
top: 0,
right: 0,
bottom: 0,
left: 0,
},
};
return (
<Chart
options={options}
series={series}
type={chartType}
height={height}
width={"100%"}
/>
);
};
export default AccountChart;

View File

@ -1,103 +0,0 @@
"use client"
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { cn } from "@/lib/utils";
import { useTranslations } from "next-intl";
import { Link } from '@/i18n/routing';
import { useState } from "react";
const users = [
{
name: "Ab",
},
{
name: "Bc",
},
{
name: "Cd",
},
{
name: "Df",
},
{
name: "Ab",
},
{
name: "Sd",
},
{
name: "Sg",
},
];
const AmountTransfer = () => {
const t = useTranslations("BankingDashboard");
const [activeIndex, setActiveIndex] = useState(0);
return (
<div className="space-y-6">
<div className="bg-default-50 rounded-md p-4">
<div className="flex items-center gap-2 mb-2">
<div className="text-lg text-default-900 flex-1">{t("contacts")}</div>
<Link
href="#"
className="flex-none font-medium text-default-900 underline text-sm"
>
{t("view_all")}
</Link>
</div>
<div className="flex overflow-x-auto gap-6 py-3 px-1">
{users.map((user, index) => (
<Avatar
key={index}
color="primary"
className={cn("", {
"ring-2 ring-primary ring-offset-2": index === activeIndex,
})}
onClick={() => setActiveIndex(index)}
>
<AvatarFallback className="text-lg">{user.name}</AvatarFallback>
</Avatar>
))}
</div>
</div>
<div className="bg-default-100 rounded-md p-4">
<Label
className="text-xs text-default-500 mb-1 cursor-pointer font-normal"
htmlFor="cdp"
>
{t("total_amount")}
</Label>
<Input
placeholder="$6547"
id="cdp"
className="bg-transparent border-none px-0 py-0 placeholder:text-default-400 text-base font-medium text-default-900"
/>
</div>
<div className="bg-default-100 rounded-md p-4">
<Label
className="text-xs text-default-500 mb-1 cursor-pointer font-normal"
htmlFor="cd"
>
{t("recipient_account_number")}
</Label>
<Input
placeholder="3458-3548-6548-3244"
id="cd"
className="bg-transparent border-none px-0 py-0 placeholder:text-default-400 text-base font-medium text-default-900"
/>
</div>
<div className="flex items-center gap-2">
<div className="flex-1">
<div className="text-xs text-default-500 mb-1">
{t("total_amount")}
</div>
<div className="text-lg font-medium text-default-900">$6547</div>
</div>
<Button className="flex-none"> {t("send_money")} </Button>
</div>
</div>
);
};
export default AmountTransfer;

View File

@ -1,68 +0,0 @@
"use client"
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import "swiper/css/effect-cards";
import { EffectCards } from 'swiper/modules';
import Image from "next/image";
import { cn } from "@/lib/utils";
import { useTranslations } from "next-intl";
const cardLists = [
{
bg: "from-[#1EABEC] to-primary ",
cardNo: "**** **** **** 3945",
balance: "10,975"
},
{
bg: "from-[#4C33F7] to-[#801FE0] ",
cardNo: "**** **** **** 3945",
balance: "12,975"
},
{
bg: "from-[#FF9838] to-[#008773]",
cardNo: "**** **** **** 3945",
balance: "14,985"
}
];
const CardSlider = () => {
const t = useTranslations("BankingDashboard");
return (
<Swiper effect={"cards"} grabCursor={true} modules={[EffectCards]}>
{cardLists.map((item, i) => (
<SwiperSlide key={i}>
<div
className={cn(
"h-[200px] bg-gradient-to-r relative rounded-md p-4 text-white ",
item.bg
)}
>
<Image
src="/images/all-img/visa-card-bg.png"
alt=""
fill
sizes="(100vw, 100vh)"
priority
/>
<div className="relative ">
<Image
src="/images/logo/visa.svg"
height={48}
width={90}
className="w-20 h-10"
alt=""
/>
<div className="mt-[18px] font-semibold text-lg mb-[17px]">
{item.cardNo}
</div>
<div className="text-xs text-opacity-75 mb-0.5">
{t("current_balance")}
</div>
<div className="text-2xl font-semibold">${item.balance}</div>
</div>
</div>
</SwiperSlide>
))}
</Swiper>
);
};
export default CardSlider;

View File

@ -1,111 +0,0 @@
"use client";
import dynamic from "next/dynamic";
const Chart = dynamic(() => import("react-apexcharts"), { ssr: false });
import { useTheme } from "next-themes";
import { useConfig } from "@/hooks/use-config";
import {
getGridConfig,
getXAxisConfig,
getYAxisConfig,
} from "@/lib/appex-chart-options";
import { colors } from "@/lib/colors";
interface HistoryChartProps {
height?: number;
series?: {
name: string;
data: number[]
}[];
}
const HistoryChart = ({
height = 360,
series = [
{
name: "Earnings",
data: [31, 40, 28, 51, 42, 109, 100],
},
{
name: "Expenses",
data: [11, 32, 45, 32, 34, 52, 41],
}
]
}: HistoryChartProps
) => {
const [config] = useConfig();
const { theme: mode } = useTheme();
const options: any = {
chart: {
toolbar: {
show: false,
},
},
dataLabels: {
enabled: false,
},
stroke: {
curve: "straight",
width: 2,
},
colors: [colors.primary, colors.warning],
tooltip: {
theme: mode === "dark" ? "dark" : "light",
},
grid: getGridConfig(),
fill: {
type: "gradient",
gradient: {
shadeIntensity: 0.3,
opacityFrom: 0.4,
opacityTo: 0.5,
stops: [0, 30, 0],
}
},
yaxis: getYAxisConfig(mode === 'light' ? colors["default-600"] : colors["default-300"]),
xaxis: getXAxisConfig(
mode === 'light' ? colors["default-600"] : colors["default-300"]
),
legend: {
offsetY: 4,
show: true,
fontSize: "12px",
fontFamily: "Inter",
labels: {
colors: mode === 'light' ? colors["default-600"] : colors["default-300"],
},
markers: {
width: 6,
height: 6,
offsetY: 0,
offsetX: -5,
radius: 12,
},
itemMargin: {
horizontal: 18,
vertical: 0,
},
},
padding: {
top: 0,
right: 0,
bottom: 0,
left: 0,
},
};
return (
<Chart
options={options}
series={series}
type="area"
height={height}
width={"100%"}
/>
);
};
export default HistoryChart;

View File

@ -1,132 +0,0 @@
"use client"
import {
ColumnDef,
} from "@tanstack/react-table"
import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { cn } from "@/lib/utils"
export type DataProps = {
id: string | number;
customer: {
name: string;
image: string;
};
history: {
transId: string;
},
date: string;
amount: string;
status?: "paid" | "due" | "cancel";
action: React.ReactNode;
}
export const columns: ColumnDef<DataProps>[] = [
{
accessorKey: "customer",
header: "Customer",
cell: ({ row }) => {
const user = row.original.customer;
return (
<div className="font-medium text-card-foreground/80">
<div className="flex gap-3 items-center">
<Avatar
className="rounded-full w-8 h-8"
>
{user?.image ? (
<AvatarImage src={user.image} />
) : (
<AvatarFallback>AB</AvatarFallback>
)}
</Avatar>
<span className="text-sm text-default-600 whitespace-nowrap">
{user?.name ?? "Unknown User"}
</span>
</div>
</div>
)
}
},
{
accessorKey: "history",
header: "History",
cell: ({ row }) => {
return (
<div>
<div className="text-default-600">
Transfer
</div>
<div className="text-default-500 text-xs">
Trans ID: {row.original.history.transId}
</div>
</div>
)
}
},
{
accessorKey: "date",
header: "Date",
cell: ({ row }) => {
return (
<span>{row.getValue("date")}</span>
)
}
},
{
accessorKey: 'status',
header: 'Amount',
cell: ({ row }) => {
const status = (row.getValue<string>('status') || 'paid') as 'paid' | 'due' | 'cancel';
const classes: { [key in 'paid' | 'due' | 'cancel']: string } = {
paid: 'text-primary',
due: 'text-warning',
cancel: 'text-destructive',
};
return <span className={cn(classes[status])}>{row.original.amount}</span>;
}
},
{
id: "actions",
accessorKey: "action",
header: "Actions",
enableHiding: false,
cell: ({ row }) => {
return (
<div className="flex justify-end">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
size="icon"
className="bg-transparent text-default-700 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 " />
</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 group 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>
</div>
)
}
}
]

View File

@ -1,60 +0,0 @@
import { DataProps } from "./columns";
export const data: DataProps[] = [
{
id: 1,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "3/26/2022",
history: {
transId: "8HG654Pk32",
},
amount: "$1779.53",
status:"paid",
action: null,
},
{
id: 2,
customer: {
name: "Emily Davis",
image: "/images/all-img/cus-1.png",
},
date: "2/6/2022",
history: {
transId: "8HG654Pk33"
},
amount: "$2215.78",
status:"due",
action: null,
},
{
id: 3,
customer: {
name: "Laura Smith",
image: "/images/avatar/avatar-1.png",
},
date: "9/6/2021",
history: {
transId: "8HG654Pk34"
},
amount: "$3183.60",
status:"cancel",
action: null,
},
{
id: 4,
customer: {
name: "Sarah Johnson",
image: "/images/avatar/avatar-2.png",
},
date: "11/7/2021",
history: {
transId: "8HG654Pk35"
},
amount: "$2587.86",
status:"paid",
action: null,
}
];

View File

@ -1,15 +0,0 @@
import { Metadata } from "next";
export const metadata:Metadata={
title: 'Banking Page',
description: 'Banking Page Description'
}
const Layout = ({children}: {children: React.ReactNode}) => {
return (
<>
{children}
</>
);
};
export default Layout;

View File

@ -1,134 +0,0 @@
import { StatusBlock } from "@/components/blocks/status-block";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
import CardSlider from "./components/card-slider";
import AmountTransfer from "./components/amount-transfer";
import TransactionsTable from "./components/transactions";
import DashboardDropdown from "@/components/dashboard-dropdown";
import HistoryChart from "./components/history-chart";
import AccountChart from "./components/account-chart";
import { useTranslations } from "next-intl";
const BankingPage = () => {
const t = useTranslations("BankingDashboard");
return (
<div className="space-y-5">
<Card>
<CardContent className=" p-6">
<div className="grid xl:grid-cols-4 lg:grid-cols-2 md:grid-cols-2 grid-cols-1 gap-5 place-content-center">
<div className="flex space-x-4 h-full items-center rtl:space-x-reverse">
<div className="flex-none">
<Avatar className="h-20 w-20 bg-transparent hover:bg-transparent">
<AvatarImage src="/images/all-img/main-user.png" />
<AvatarFallback>SA</AvatarFallback>
</Avatar>
</div>
<div className="flex-1">
<h4 className="text-xl font-medium mb-2">
<span className="block font-light text-default-800">
{t("widget_title")},
</span>
<span className="block text-default-900">Mr. Jone Doe</span>
</h4>
<p className="text-sm text-default-600">{t("widget_desc")}</p>
</div>
</div>
{/* status blocks */}
<StatusBlock
title={t("current_balance")}
total="$34,564"
chartType="bar"
className="bg-default-50 shadow-none border-none"
opacity={1}
/>
<StatusBlock
title={t("credit")}
total="$3,564"
chartColor="#80fac1"
className="bg-default-50 shadow-none border-none"
series={[40, 70, 45, 100, 75, 40, 80, 90]}
chartType="bar"
opacity={1}
/>
<StatusBlock
title={t("debit")}
total="$3,564"
chartColor="#ffbf99"
className="bg-default-50 shadow-none border-none"
chartType="bar"
series={[40, 70, 45, 100, 75, 40, 80, 90]}
opacity={1}
/>
</div>
</CardContent>
</Card>
<div className="grid grid-cols-12 gap-5">
<div className="lg:col-span-4 col-span-12 space-y-5">
<Card>
<CardHeader>
<CardTitle>{t("my_card")}</CardTitle>
</CardHeader>
<CardContent>
<div className="max-w-[90%] mx-auto mt-2">
<CardSlider />
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>{t("quick_transfer")}</CardTitle>
</CardHeader>
<CardContent>
<AmountTransfer />
</CardContent>
</Card>
</div>
<div className="lg:col-span-8 col-span-12 space-y-5">
<Card>
<CardContent className="p-0">
<TransactionsTable />
</CardContent>
</Card>
<Card>
<CardHeader className="flex-row gap-1">
<CardTitle className="flex-1">{t("history")}</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<HistoryChart />
</CardContent>
</Card>
</div>
</div>
<div className="grid lg:grid-cols-2 grid-cols-1 gap-5">
<Card>
<CardHeader className="flex-row gap-1">
<CardTitle className="flex-1">{t("account_receivable")}</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<AccountChart />
</CardContent>
</Card>
<Card>
<CardHeader className="flex-row gap-1">
<CardTitle className="flex-1">{t("account_payable")}</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<AccountChart
series={[
{
data: [31, 40, 28, 51, 42, 109, 100],
},
]}
chartColor="primary"
/>
</CardContent>
</Card>
</div>
</div>
);
};
export default BankingPage;

View File

@ -1,144 +0,0 @@
"use client";
import dynamic from "next/dynamic";
const Chart = dynamic(() => import("react-apexcharts"), { ssr: false });
import { colors } from "@/lib/colors";
import { useTheme } from "next-themes";
import { useConfig } from "@/hooks/use-config";
import { getGridConfig, getYAxisConfig } from "@/lib/appex-chart-options";
interface DealsDistributionChartProps {
height?: number;
series?: {
name: string;
data: number[];
}[];
}
const defaultSeries = [
{
name: "Sales qualified",
data: [44, 55, 57, 56, 61, 58, 63, 60, 66],
},
{
name: "Meeting",
data: [76, 85, 101, 98, 87, 105, 91, 114, 94],
},
{
name: "In negotiation",
data: [35, 41, 36, 26, 45, 48, 52, 53, 41],
}
];
const DealDistributionsChart = ({ series = defaultSeries, height = 410 }: DealsDistributionChartProps) => {
const [config] = useConfig();
const { theme: mode } = useTheme();
const options: any = {
chart: {
toolbar: {
show: false,
},
stacked: true,
},
plotOptions: {
bar: {
dataLabels: {
total: {
enabled: false,
}
},
columnWidth:"55%"
}
},
dataLabels: {
enabled: false,
offsetX: 0,
style: {
fontSize: "12px",
colors: [
mode === 'light' ? colors["default-600"] : colors["default-300"]
]
}
},
stroke: {
show: false,
width: 1,
colors: [
mode === 'light' ? colors["default-600"] : colors["default-300"],
],
},
colors: [
colors.primary,
colors.info,
colors.warning,
],
tooltip: {
theme: mode === "dark" ? "dark" : "light",
},
grid: getGridConfig(),
yaxis: getYAxisConfig(
mode === 'light' ? colors["default-600"] : colors["default-300"]
),
xaxis: {
categories: [
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
],
axisBorder: {
show: false,
},
axisTicks: {
show: false,
},
labels: {
style: {
colors: mode === 'light' ? colors["default-600"] : colors["default-300"]
}
}
},
padding: {
top: 0,
right: 0,
bottom: 0,
left: 0,
},
legend: {
show: true,
position: "bottom",
horizontalAlign: "center",
fontSize: "12px",
fontFamily: "Inter",
offsetY: 0,
labels: {
colors: mode === 'light' ? colors["default-600"] : colors["default-300"],
},
markers: {
width: 6,
height: 6,
radius: 12,
offsetX: config.isRtl ? 5 : -5
}
},
itemMargin: {
horizontal: 18,
vertical: 0,
}
}
return (
<Chart
options={options}
series={series}
type="bar"
height={height}
width={"100%"}
/>
);
};
export default DealDistributionsChart;

View File

@ -1,202 +0,0 @@
"use client"
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip"
import {
ColumnDef,
} from "@tanstack/react-table"
import { Eye, SquarePen, Trash2 } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import { cn } from "@/lib/utils";
export type DataProps = {
id: string | number;
order: number;
customer: {
name: string;
image: string;
};
date: string;
quantity: number;
amount: string;
status: "paid" | "due" | "canceled";
action: React.ReactNode;
}
export const columns: ColumnDef<DataProps>[] = [
{
id: "select",
header: ({ table }) => (
<Checkbox
checked={
table.getIsAllPageRowsSelected() ||
(table.getIsSomePageRowsSelected() && "indeterminate")
}
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
aria-label="Select all"
/>
),
cell: ({ row }) => (
<div className="xl:w-16">
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
aria-label="Select row"
/>
</div>
),
enableSorting: false,
enableHiding: false,
},
{
accessorKey: "id",
header: "id",
cell: ({ row }) => <span>{row.getValue("id")}</span>,
},
{
accessorKey: "order",
header: "Order",
cell: ({ row }) => <span>{row.getValue("order")}</span>,
},
{
accessorKey: "customer",
header: "Customer",
cell: ({ row }) => {
const user = row.original.customer;
return (
<div className="font-medium text-card-foreground/80">
<div className="flex gap-3 items-center">
<Avatar
className="rounded-full w-8 h-8"
>
{user?.image ? (
<AvatarImage src={user.image} />
) : (
<AvatarFallback>AB</AvatarFallback>
)}
</Avatar>
<span className="text-sm text-default-600 whitespace-nowrap">
{user?.name ?? "Unknown User"}
</span>
</div>
</div>
)
}
},
{
accessorKey: "date",
header: "Date",
cell: ({ row }) => {
return (
<span>{row.getValue("date")}</span>
)
}
},
{
accessorKey: "quantity",
header: "Quantity",
cell: ({ row }) => {
return (
<span>{row.getValue("quantity")}</span>
)
}
},
{
accessorKey: "amount",
header: "Amount",
cell: ({ row }) => {
return (
<span>{row.getValue("amount")}</span>
)
}
},
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => {
const statusColors: Record<string, string> = {
paid: "bg-success/20 text-success",
due: "bg-warning/20 text-warning",
canceled: "bg-destructive/20 text-destructive"
};
const status = row.getValue<string>("status");
const statusStyles = statusColors[status] || "default";
return (
<Badge
className={cn("rounded-full px-5", statusStyles)}
>{status} </Badge>
);
}
},
{
id: "actions",
accessorKey: "action",
header: "Action",
enableHiding: false,
cell: ({ row }) => {
return (
<div className="flex items-center gap-2">
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="outline"
size="icon"
className="w-7 h-7 ring-offset-transparent border-default-300 text-default-500"
color="secondary"
>
<Eye className="w-4 h-4" />
</Button>
</TooltipTrigger>
<TooltipContent side="top">
<p>View</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="outline"
size="icon"
className="w-7 h-7 ring-offset-transparent border-default-300 text-default-500"
color="secondary"
>
<SquarePen className="w-4 h-4" />
</Button>
</TooltipTrigger>
<TooltipContent side="top">
<p>Edit</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="outline"
size="icon"
className="w-7 h-7 ring-offset-transparent border-default-300 text-default-500"
color="secondary"
>
<Trash2 className="w-4 h-4" />
</Button>
</TooltipTrigger>
<TooltipContent side="top" className="bg-destructive text-destructive-foreground">
<p>Delete</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
)
}
}
]

View File

@ -1,654 +0,0 @@
import { DataProps } from "./columns";
export const data: DataProps[] = [
{
id: 1,
order: 951,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "3/26/2022",
quantity: 13,
amount: "$1779.53",
status: "paid",
action: null,
},
{
id: 2,
order: 238,
customer: {
name: "Emily Davis",
image: "/images/all-img/cus-1.png",
},
date: "2/6/2022",
quantity: 13,
amount: "$2215.78",
status: "due",
action: null,
},
{
id: 3,
order: 339,
customer: {
name: "Laura Smith",
image: "/images/avatar/avatar-1.png",
},
date: "9/6/2021",
quantity: 1,
amount: "$3183.60",
status: "due",
action: null,
},
{
id: 4,
order: 365,
customer: {
name: "Sarah Johnson",
image: "/images/avatar/avatar-2.png",
},
date: "11/7/2021",
quantity: 13,
amount: "$2587.86",
status: "canceled",
action: null,
},
{
id: 5,
order: 513,
customer: {
name: "Rachel Brown",
image: "/images/avatar/avatar-3.png",
},
date: "5/6/2022",
quantity: 12,
amount: "$3840.73",
status: "paid",
action: null,
},
{
id: 6,
order: 534,
customer: {
name: "Megan Taylor",
image: "/images/avatar/avatar-4.png",
},
date: "2/14/2022",
quantity: 12,
amount: "$4764.18",
status: "canceled",
action: null,
},
{
id: 7,
order: 77,
customer: {
name: "Sophie Clark",
image: "/images/avatar/avatar-5.png",
},
date: "7/30/2022",
quantity: 6,
amount: "$2875.05",
status: "paid",
action: null,
},
{
id: 8,
order: 238,
customer: {
name: "Natalie Martin",
image: "/images/avatar/avatar-6.png",
},
date: "6/30/2022",
quantity: 9,
amount: "$2491.02",
status: "due",
action: null,
},
{
id: 9,
order: 886,
customer: {
name: "Hannah Lewis",
image: "/images/avatar/avatar-7.png",
},
date: "8/9/2022",
quantity: 8,
amount: "$3006.95",
status: "due",
action: null,
},
{
id: 10,
order: 3,
customer: {
name: "Lisa White",
image: "/images/avatar/avatar-8.png",
},
date: "8/4/2022",
quantity: 12,
amount: "$2160.32",
status: "paid",
action: null,
},
{
id: 11,
order: 198,
customer: {
name: "Emma Walker",
image: "/images/avatar/avatar-9.png",
},
date: "4/5/2022",
quantity: 8,
amount: "$1272.66",
status: "paid",
action: null,
},
{
id: 12,
order: 829,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-10.png",
},
date: "8/9/2022",
quantity: 2,
amount: "$4327.86",
status: "canceled",
action: null,
},
{
id: 13,
order: 595,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-11.png",
},
date: "2/10/2022",
quantity: 11,
amount: "$3671.81",
status: "canceled",
action: null,
},
{
id: 14,
order: 374,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-12.png",
},
date: "2/10/2022",
quantity: 2,
amount: "$3401.82",
status: "paid",
action: null,
},
{
id: 15,
order: 32,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-1.png",
},
date: "5/20/2022",
quantity: 4,
amount: "$2387.49",
status: "canceled",
action: null,
},
{
id: 16,
order: 89,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-2.png",
},
date: "5/3/2022",
quantity: 15,
amount: "$4236.61",
status: "due",
action: null,
},
{
id: 17,
order: 912,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-3.png",
},
date: "10/31/2021",
quantity: 11,
amount: "$2975.66",
status: "paid",
action: null,
},
{
id: 18,
order: 621,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-4.png",
},
date: "1/13/2022",
quantity: 5,
amount: "$4576.13",
status: "canceled",
action: null,
},
{
id: 19,
order: 459,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-5.png",
},
date: "6/14/2022",
quantity: 5,
amount: "$1276.56",
status: "canceled",
action: null,
},
{
id: 20,
order: 108,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-6.png",
},
date: "10/8/2021",
quantity: 4,
amount: "$1078.64",
status: "due",
action: null,
},
{
id: 21,
order: 492,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-7.png",
},
date: "11/17/2021",
quantity: 9,
amount: "$1678.19",
status: "paid",
action: null,
},
{
id: 22,
order: 42,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-8.png",
},
date: "4/4/2022",
quantity: 9,
amount: "$1822.02",
status: "canceled",
action: null,
},
{
id: 23,
order: 841,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-9.png",
},
date: "3/21/2022",
quantity: 5,
amount: "$1578.39",
status: "due",
action: null,
},
{
id: 24,
order: 561,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-10.png",
},
date: "6/18/2022",
quantity: 12,
amount: "$2130.49",
status: "canceled",
action: null,
},
{
id: 25,
order: 720,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-1.png",
},
date: "8/15/2022",
quantity: 8,
amount: "$3721.11",
status: "due",
action: null,
},
{
id: 26,
order: 309,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-2.png",
},
date: "4/28/2022",
quantity: 8,
amount: "$4683.45",
status: "paid",
action: null,
},
{
id: 27,
order: 24,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-3.png",
},
date: "9/6/2021",
quantity: 7,
amount: "$2863.71",
status: "paid",
action: null,
},
{
id: 28,
order: 518,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-4.png",
},
date: "9/11/2021",
quantity: 4,
amount: "$3879.41",
status: "canceled",
action: null,
},
{
id: 29,
order: 98,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-5.png",
},
date: "1/27/2022",
quantity: 5,
amount: "$4660.81",
status: "paid",
action: null,
},
{
id: 30,
order: 940,
customer: {
name: "Jenny Wilson",
image: "/images/avatar/avatar-6.png",
},
date: "9/16/2021",
quantity: 6,
amount: "$4800.75",
status: "due",
action: null,
},
{
id: 31,
order: 925,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "1/8/2022",
quantity: 1,
amount: "$2299.05",
status: "canceled",
action: null,
},
{
id: 32,
order: 122,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "11/18/2021",
quantity: 1,
amount: "$3578.02",
status: "paid",
action: null,
},
{
id: 33,
order: 371,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "3/30/2022",
quantity: 13,
amount: "$1996.06",
status: "canceled",
action: null,
},
{
id: 34,
order: 296,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "11/13/2021",
quantity: 5,
amount: "$2749.00",
status: "due",
action: null,
},
{
id: 35,
order: 887,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "12/7/2021",
quantity: 11,
amount: "$4353.01",
status: "paid",
action: null,
},
{
id: 36,
order: 30,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "9/9/2021",
quantity: 15,
amount: "$3252.37",
status: "due",
action: null,
},
{
id: 37,
order: 365,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "2/12/2022",
quantity: 5,
amount: "$4044.10",
status: "due",
action: null,
},
{
id: 38,
order: 649,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "3/6/2022",
quantity: 5,
amount: "$3859.92",
status: "paid",
action: null,
},
{
id: 39,
order: 923,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "7/25/2022",
quantity: 14,
amount: "$1652.47",
status: "paid",
action: null,
},
{
id: 40,
order: 423,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "3/2/2022",
quantity: 8,
amount: "$2700.12",
status: "canceled",
action: null,
},
{
id: 41,
order: 703,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "12/8/2021",
quantity: 8,
amount: "$4508.13",
status: "canceled",
action: null,
},
{
id: 42,
order: 792,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "11/22/2021",
quantity: 11,
amount: "$4938.04",
status: "due",
action: null,
},
{
id: 43,
order: 400,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "4/6/2022",
quantity: 1,
amount: "$3471.32",
status: "due",
action: null,
},
{
id: 44,
order: 718,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "2/4/2022",
quantity: 4,
amount: "$4011.60",
status: "paid",
action: null,
},
{
id: 45,
order: 970,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "3/30/2022",
quantity: 15,
amount: "$3723.64",
status: "due",
action: null,
},
{
id: 46,
order: 786,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "11/20/2021",
quantity: 2,
amount: "$2441.15",
status: "canceled",
action: null,
},
{
id: 47,
order: 925,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "10/24/2021",
quantity: 11,
amount: "$1196.76",
status: "canceled",
action: null,
},
{
id: 48,
order: 929,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "6/30/2022",
quantity: 10,
amount: "$3579.57",
status: "canceled",
action: null,
},
{
id: 49,
order: 377,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "11/16/2021",
quantity: 4,
amount: "$2657.84",
status: "due",
action: null,
},
{
id: 50,
order: 661,
customer: {
name: "Jenny Wilson",
image: "/images/all-img/customer_1.png",
},
date: "8/15/2022",
quantity: 6,
amount: "$2905.94",
status: "paid",
action: null,
},
];

View File

@ -1,78 +0,0 @@
"use client";
import dynamic from "next/dynamic";
const Chart = dynamic(() => import("react-apexcharts"), { ssr: false });
import { colors } from "@/lib/colors";
import { useTheme } from "next-themes";
import { useConfig } from "@/hooks/use-config";
interface TrendsCalculationChartProps {
height?: number;
series?: number[];
chartLabels?:string[];
}
const TrendsCalculationChart = ({
series = [44, 55, 30],
height = 360,
chartLabels=["70% Sent", "18% Opend", "12% Rejected"],
}: TrendsCalculationChartProps) => {
const [config] = useConfig();
const { theme: mode } = useTheme();
const options: any = {
chart: {
toolbar: {
show: false,
},
},
stroke: {
width: 0
},
labels:chartLabels,
dataLabels: {
enabled: true,
style: {
fontSize: "20px",
},
},
colors: [
colors.primary,
colors.success,
colors.warning,
],
tooltip: {
theme: mode === "dark" ? "dark" : "light",
},
padding: {
top: 0,
right: 0,
bottom: 0,
left: 0,
},
legend: {
position:"bottom",
labels: {
colors: mode === 'light' ? colors["default-600"] : colors["default-300"],
},
itemMargin: {
horizontal: 5,
vertical: 5,
},
markers: {
width: 10,
height: 10,
radius: 10,
offsetX: config.isRtl ? 5 : -5
}
},
};
return (
<Chart
options={options}
series={series}
type="pie"
height={height}
width={"100%"}
/>
);
};
export default TrendsCalculationChart;

View File

@ -1,22 +0,0 @@
export const campaigns = [
{
name: "Channel",
value: "roi",
},
{
name: "Email",
value: "40%",
},
{
name: "Website",
value: "28%",
},
{
name: "Facebook",
value: "34%",
},
{
name: "Offline",
value: "17%",
}
];

View File

@ -1,15 +0,0 @@
import { Metadata } from "next";
export const metadata:Metadata={
title: 'CRM',
description: 'CRM Dashboard Description'
}
const Layout = ({children}: {children: React.ReactNode}) => {
return (
<>
{children}
</>
);
};
export default Layout;

View File

@ -1,206 +0,0 @@
import DashboardDropdown from "@/components/dashboard-dropdown";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { TrendingDown, TrendingUp } from "lucide-react";
import Image from "next/image";
import DealDistributionsChart from "./components/deal-distributions-chart";
import { campaigns } from "./data";
import TrendsCalculationChart from "./components/trends-calculation-chart";
import TransactionsTable from "./components/transactions";
import { useTranslations } from "next-intl";
const CrmPage = () => {
const t = useTranslations("CrmDashboard");
return (
<div className="space-y-5">
<div className="grid grid-cols-12 gap-5">
<div className="col-span-12 lg:col-span-8 space-y-5">
<Card>
<CardContent className="p-4">
<div className="grid xl:grid-cols-4 lg:grid-cols-2 grid-cols-1 gap-3">
<Card className="bg-warning/20 relative shadow-none border-none">
<CardContent className="p-4">
<Image
src="/images/all-img/shade-1.png"
alt="images"
draggable="false"
className="absolute top-0 start-0 w-full h-full object-contain"
width={300}
height={200}
priority
/>
<div className="mb-6 text-sm text-default-900 font-medium">
{t("sales")}
</div>
<div className=" text-2xl text-default-900 font-medium mb-6">
354
</div>
<div className="flex gap-2">
<div className="flex-none text-xl">
<TrendingUp className="w-4 h-4 text-primary" />
</div>
<div className="flex-1 text-sm">
<span className="block mb-0.2">25.67% </span>
<span className="block mb-1 text-default-600">
{t("from_last_weeks")}
</span>
</div>
</div>
</CardContent>
</Card>
<Card className="bg-info/20 relative shadow-none border-none">
<CardContent className="p-4">
<Image
src="/images/all-img/shade-2.png"
alt="images"
draggable="false"
className="absolute top-0 start-0 w-full h-full object-contain"
width={300}
height={200}
priority
/>
<div className="mb-6 text-sm text-default-900 font-medium">
{t("revenue")}
</div>
<div className=" text-2xl text-default-900 font-medium mb-6">
$86,954
</div>
<div className="flex gap-2">
<div className="flex-none text-xl">
<TrendingUp className="w-4 h-4 text-primary" />
</div>
<div className="flex-1 text-sm">
<span className="block mb-0.2">8.67% </span>
<span className="block mb-1 text-default-600">
{t("from_last_weeks")}
</span>
</div>
</div>
</CardContent>
</Card>
<Card className="bg-primary/20 relative shadow-none border-none">
<CardContent className="p-4">
<Image
src="/images/all-img/shade-3.png"
alt="images"
draggable="false"
className="absolute top-0 start-0 w-full h-full object-contain"
width={300}
height={200}
priority
/>
<div className="mb-6 text-sm text-default-900 font-medium">
{t("conversion")}
</div>
<div className=" text-2xl text-default-900 font-medium mb-6">
15%
</div>
<div className="flex gap-2">
<div className="flex-none text-xl">
<TrendingDown className="w-4 h-4 text-destructive" />
</div>
<div className="flex-1 text-sm">
<span className="block mb-0.2 text-destructive">
1.67%{" "}
</span>
<span className="block mb-1 text-default-600">
{t("from_last_weeks")}
</span>
</div>
</div>
</CardContent>
</Card>
<Card className="bg-success/20 relative shadow-none border-none">
<CardContent className=" p-4">
<Image
src="/images/all-img/shade-4.png"
alt="images"
draggable="false"
className="absolute top-0 start-0 w-full h-full object-contain"
width={300}
height={200}
priority
/>
<div className="mb-6 text-sm text-default-900 font-medium">
{t("leads")}
</div>
<div className=" text-2xl text-default-900 font-medium mb-6">
654
</div>
<div className="flex gap-2">
<div className="flex-none text-xl">
<TrendingDown className="w-4 h-4 text-primary" />
</div>
<div className="flex-1 text-sm">
<span className="block mb-0.2 text-primary">
1.67%{" "}
</span>
<span className="block mb-1 text-default-600">
{t("from_last_weeks")}
</span>
</div>
</div>
</CardContent>
</Card>
</div>
</CardContent>
</Card>
<Card>
<CardHeader className="flex-row flex-wrap gap-2">
<CardTitle className="flex-1 whitespace-nowrap">
{t("deal_distribution_by_stage")}
</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<DealDistributionsChart />
</CardContent>
</Card>
</div>
<div className="col-span-12 lg:col-span-4 space-y-5">
<Card>
<CardHeader className="flex-row gap-3">
<CardTitle className="flex-1">{t("campaigns")}</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<ul className="divide-y divide-default-100 dark:divide-default-300">
{campaigns.map((item, i) => (
<li
key={`campaign-${i}`}
className="first:text-xs text-sm text-default-600 py-2.5 px-2 first:uppercase"
>
<div className="flex justify-between">
<span>{item.name}</span>
<span>{item.value}</span>
</div>
</li>
))}
</ul>
</CardContent>
</Card>
<Card>
<CardHeader className="flex-row gap-3">
<CardTitle className="flex-1">
{t("trends_calculation")}
</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<TrendsCalculationChart />
</CardContent>
</Card>
</div>
</div>
<div>
<Card>
<CardContent className="px-0">
<TransactionsTable />
</CardContent>
</Card>
</div>
</div>
);
};
export default CrmPage;

View File

@ -1,160 +0,0 @@
"use client"
import { Progress } from "@/components/ui/progress";
import { useTranslations } from "next-intl";
import Image from "next/image";
const customers = [
{
title: "Nicole Kidman",
img: "/images/all-img/cus-1.png",
value: 70,
bg: "before:bg-info/30",
barColor: "info",
number: 2,
},
{
title: "Monica Bellucci",
img: "/images/all-img/cus-2.png",
value: 80,
bg: "before:bg-warning/30",
barColor: "warning",
active: true,
number: 1,
},
{
title: "Pamela Anderson",
img: "/images/all-img/cus-3.png",
value: 65,
bg: "before:bg-success/30",
barColor: "success",
number: 3,
},
{
title: "Dianne Russell",
img: "/images/users/user-1.jpg",
value: 60,
bg: "before:bg-info/30",
barColor: "info",
number: 4,
},
{
title: "Robert De Niro",
img: "/images/users/user-2.jpg",
value: 50,
bg: "before:bg-warning/30",
barColor: "warning",
number: 5,
},
{
title: "De Niro",
img: "/images/users/user-3.jpg",
value: 60,
bg: "before:bg-warning/30",
barColor: "warning",
number: 6,
}
];
const CustomerList = ({ item }: any) => {
const t = useTranslations("EcommerceDashboard");
return (
<div className="relative p-4 rounded md:flex items-center md:space-x-10 md:space-y-0 space-y-3 rtl:space-x-reverse">
<div
className={`${
item.active ? "ring-2 ring-[#FFC155]" : ""
} h-10 w-10 rounded-full relative`}
>
{item.active && (
<span className="crown absolute -top-[14px] left-1/2 -translate-x-1/2">
<Image
width={40}
height={40}
className="w-7 h-7"
src="/images/icon/crown.svg"
alt=""
/>
</span>
)}
<Image
src={item.img}
alt=""
width={100}
height={100}
className="w-full h-full rounded-full"
priority
/>
<span className="h-4 w-4 absolute right-0 bottom-0 rounded-full bg-[#FFC155] border border-white flex flex-col items-center justify-center text-white text-[10px] font-medium">
{item.number}
</span>
</div>
<h4 className="text-sm text-default-600 font-semibold">{item.title}</h4>
<div className="inline-block text-center bg-default-900 text-default-100 px-2.5 py-1.5 text-xs font-medium rounded-full min-w-[60px]">
{item.value}
</div>
<div className="flex-1">
<div className="flex justify-between text-sm font-normal mb-3">
<span>{t("progress")}</span>
<span className="font-normal">{item.value}%</span>
</div>
<Progress value={item.value} color={item.barColor} size="sm" />
</div>
</div>
);
}
const CustomerCard = ({ item }: any) => {
const t = useTranslations("EcommerceDashboard");
return <div
className={` relative z-[1] text-center p-4 rounded before:w-full before:h-[calc(100%-60px)] before:absolute before:left-0 before:top-[60px] before:rounded before:z-[-1] before:bg-opacity-[0.1] ${item.bg}`}
>
<div
className={`${item.active ? "ring-2 ring-[#FFC155]" : ""
} h-[70px] w-[70px] rounded-full mx-auto mb-4 relative`}
>
{item.active && (
<span className="crown absolute -top-[24px] left-1/2 -translate-x-1/2">
<Image width={40} height={40} className="w-7 h-7" src="/images/icon/crown.svg" alt="" />
</span>
)}
<Image
src={item.img}
alt=""
width={100}
height={100}
className="w-full h-full rounded-full"
priority
/>
<span className="h-[27px] w-[27px] absolute right-0 bottom-0 rounded-full bg-[#FFC155] border border-white flex flex-col items-center justify-center text-white text-xs font-medium">
{item.number}
</span>
</div>
<h4 className="text-sm text-default-600 font-semibold mb-4">
{item.title}
</h4>
<div className="inline-block bg-default-900 text-default-100 px-2.5 py-1.5 text-xs font-medium rounded-full min-w-[60px]">
{item.value}
</div>
<div>
<div className="flex justify-between text-sm font-normal mb-3 mt-4">
<span>{t("progress")}</span>
<span className="font-normal">{item.value}%</span>
</div>
<Progress value={item.value} color={item.barColor} size="sm" />
</div>
</div>;
};
const Customer = () => {
const t = useTranslations("EcommerceDashboard");
return (
<div className="pb-2">
<div className="grid md:grid-cols-3 grid-cols-1 gap-5">
{customers.slice(0, 3).map((item, i) => <CustomerCard item={item} key={`customer-${i}`} />)}
</div>
<div className="grid grid-cols-1 gap-5 mt-5">
{customers.slice(3, 8).map((item, i) => <CustomerList item={item} key={`customer-item-${i}`} />)}
</div>
</div>
);
};
export default Customer;

View File

@ -1,284 +0,0 @@
import { OrdersDataProps } from "./recent-order-table";
export const data:OrdersDataProps[] = [
{
user: {
name: "Esther Howard",
image: "/images/users/user-1.jpg",
},
product: "Headphone",
invoice: "#324567",
price: "$90.99",
status: "paid",
},
{
user: {
name: "Guy Hawkins",
image: "/images/users/user-2.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$78.65",
status: "due",
},
{
user: {
name: "Bessie Cooper",
image: "/images/users/user-3.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$78.65",
status: "pending",
},
{
user: {
name: "Kathryn Murphy",
image: "/images/users/user-4.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$38.65",
status: "cancled",
},
{
user: {
name: "Darrell Steward",
image: "/images/users/user-5.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$178.65",
status: "shipped",
},
{
user: {
name: "Darrell Steward",
image: "/images/users/user-6.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$74.65",
status: "cancled",
},
{
user: {
name: "Esther Howard",
image: "/images/users/user-1.jpg",
},
product: "Headphone",
invoice: "#324567",
price: "$90.99",
status: "paid",
},
{
user: {
name: "Guy Hawkins",
image: "/images/users/user-2.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$78.65",
status: "due",
},
{
user: {
name: "Bessie Cooper",
image: "/images/users/user-3.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$78.65",
status: "pending",
},
{
user: {
name: "Kathryn Murphy",
image: "/images/users/user-4.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$38.65",
status: "cancled",
},
{
user: {
name: "Darrell Steward",
image: "/images/users/user-5.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$178.65",
status: "shipped",
},
{
user: {
name: "Darrell Steward",
image: "/images/users/user-6.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$74.65",
status: "cancled",
},
{
user: {
name: "Esther Howard",
image: "/images/users/user-1.jpg",
},
product: "Headphone",
invoice: "#324567",
price: "$90.99",
status: "paid",
},
{
user: {
name: "Guy Hawkins",
image: "/images/users/user-2.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$78.65",
status: "due",
},
{
user: {
name: "Bessie Cooper",
image: "/images/users/user-3.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$78.65",
status: "pending",
},
{
user: {
name: "Kathryn Murphy",
image: "/images/users/user-4.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$38.65",
status: "cancled",
},
{
user: {
name: "Darrell Steward",
image: "/images/users/user-5.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$178.65",
status: "shipped",
},
{
user: {
name: "Darrell Steward",
image: "/images/users/user-6.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$74.65",
status: "cancled",
},
{
user: {
name: "Esther Howard",
image: "/images/users/user-1.jpg",
},
product: "Headphone",
invoice: "#324567",
price: "$90.99",
status: "paid",
},
{
user: {
name: "Guy Hawkins",
image: "/images/users/user-2.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$78.65",
status: "due",
},
{
user: {
name: "Bessie Cooper",
image: "/images/users/user-3.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$78.65",
status: "pending",
},
{
user: {
name: "Kathryn Murphy",
image: "/images/users/user-4.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$38.65",
status: "cancled",
},
{
user: {
name: "Darrell Steward",
image: "/images/users/user-5.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$178.65",
status: "shipped",
},
{
user: {
name: "Darrell Steward",
image: "/images/users/user-6.jpg",
},
product: "Headphone",
invoice: "#4224",
price: "$74.65",
status: "cancled",
},
];
export const products = [
{
img: "/images/all-img/p-1.png",
price: "$150.00",
title: "Car engine oil",
href:"#"
},
{
img: "/images/all-img/p-2.png",
price: "$150.00",
title: "Car engine oil",
href:"#"
},
{
img: "/images/all-img/p-3.png",
price: "$150.00",
title: "Car engine oil",
href:"#"
},
{
img: "/images/all-img/p-4.png",
price: "$150.00",
title: "Car engine oil",
href:"#"
},
{
img: "/images/all-img/p-5.png",
price: "$150.00",
title: "Car engine oil",
href:"#"
},
{
img: "/images/all-img/p-6.png",
price: "$150.00",
title: "Car engine oil",
href:"#"
},
];

View File

@ -1,97 +0,0 @@
"use client"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import world from "./world-map.json";
import { VectorMap } from "@south-paw/react-vector-maps";
import { useState } from "react";
import { cn } from "@/lib/utils";
import { useTranslations } from "next-intl";
const sales = [
{
title: "Nevada",
amount: "$125k",
cls: "bg-primary/70 ring-primary/30",
},
{
title: "Colorado",
amount: "$325k",
cls: "bg-success/70 ring-success/30",
},
{
title: "Iowa",
amount: "$67",
cls: "bg-info/70 ring-info/30",
},
{
title: "Arkansas",
amount: "$354k",
cls: "bg-warning/70 ring-warning/30",
},
{
title: "Wyoming",
amount: "$195k",
cls: "bg-success/70 ring-success/30",
},
{
title: "Other countries",
amount: "$295k",
cls: "bg-secondary/70 ring-secondary/30",
},
];
const MostSales = () => {
const [filterMap, setFilterMap] = useState("usa");
const t = useTranslations("EcommerceDashboard");
return (
<Card>
<CardHeader className="flex flex-row items-center">
<CardTitle className="flex-1">{t("most_sales_map_title")}</CardTitle>
<div className="border border-default-200 dark:border-default-300 rounded p-1 flex items-center bg-background">
<span
className={cn(
"flex-1 text-sm font-normal px-3 py-1 transition-all duration-150 rounded cursor-pointer",
{
"bg-default-900 text-primary-foreground":
filterMap === "global",
}
)}
onClick={() => setFilterMap("global")}
>
{t("total_earning_map_button_1")}
</span>
<span
className={cn(
"flex-1 text-sm font-normal px-3 py-1 transition-all duration-150 rounded cursor-pointer",
{ "bg-default-900 text-primary-foreground": filterMap === "usa" }
)}
onClick={() => setFilterMap("usa")}
>
USA
</span>
</div>
</CardHeader>
<CardContent>
<VectorMap {...world} className="h-[280px] w-full dash-codevmap" />
<ul className="bg-default-50 rounded p-4 min-w-[184px] mt-8 flex justify-between flex-wrap items-center text-center">
{sales.map((item, i) => (
<li key={i} className="text-sm text-default-600">
<div className="flex items-center gap-2">
<span
className={cn(
"inline-flex h-1.5 w-1.5 bg-primary/60 ring-opacity-25 rounded-full ring-4",
item.cls
)}
></span>
<span>{item.title}</span>
</div>
<div className="block mt-1">{item.amount}</div>
</li>
))}
</ul>
</CardContent>
</Card>
);
};
export default MostSales;

View File

@ -1,43 +0,0 @@
import { Button } from "@/components/ui/button";
import { useTranslations } from "next-intl";
import Image from "next/image";
import { Link } from '@/i18n/routing';
interface Product {
img: string;
price: string;
title: string;
href: string
}
const Product = ({ product }: { product: Product }) => {
const { img, href, price, title } = product;
const t = useTranslations("EcommerceDashboard");
return (
<div className="bg-default-50 p-4 rounded text-center">
<div className="h-12 w-12 rounded-full mb-4 mx-auto">
<Image
src={img}
alt=""
height={100}
width={100}
className="w-full h-full rounded-full"
/>
</div>
<div className="text-default-500 text-sm mb-1 font-normal">
{" "}
{price}{" "}
</div>
<div className="text-default-600 text-sm mb-4">{title}</div>
<Button
asChild
color="secondary"
size="md"
fullWidth
>
<Link href={href}> {t("best_selling_products_button")}</Link>
</Button>
</div>
);
};
export default Product;

View File

@ -1,211 +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 { ChevronLeft, ChevronRight } from "lucide-react"
import { Badge } from "@/components/ui/badge"
import { cn } from "@/lib/utils"
export type OrdersDataProps = {
user: {
name: string;
image: string;
}
product: string;
invoice: string;
price: string;
status: "paid" | "due" | "pending" | "cancled" | "shipped";
}
export const columns: ColumnDef<OrdersDataProps>[] = [
{
accessorKey: "user",
header: "User",
cell: ({ row }) => (
<div className="flex items-center gap-5">
<div className="flex-none">
<div className="w-8 h-8">
<Avatar>
<AvatarImage src={row.original.user.image}></AvatarImage>
<AvatarFallback>SC</AvatarFallback>
</Avatar>
</div>
</div>
<div className="flex-1 text-start">
{row.original.user.name}
</div>
</div>
),
},
{
accessorKey: "invoice",
header: "Invoice",
cell: ({ row }) => (
<span>{row.getValue("invoice")}</span>
),
},
{
accessorKey: "price",
header: "Price",
cell: ({ row }) => (
<span>{row.getValue("price")}</span>
)
},
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => {
const status = row.getValue("status") as string;
const statusClass:{[key: string]: string} = {
"paid": "bg-success/10 text-success",
"due": "bg-warning/10 text-warning",
"pending": "bg-primary/10 text-primary",
"cancled": "bg-destructive/10 text-destructive",
"shipped": "bg-warning/10 text-warning",
}
const className = statusClass[status] || "bg-default/10 text-default";
return (
<Badge className={cn("px-3 min-w-[90px] justify-center py-1 rounded-full",className)}>{status}</Badge>
)
}
}
]
const RecentOrderTable = () => {
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 gap-2 flex-none py-4">
<Button
variant="outline"
size="icon"
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
className='w-8 h-8 border-transparent hover:bg-transparent'
>
<ChevronLeft className='w-5 h-5 text-default-900' />
</Button>
{table.getPageOptions().map((page, pageIndex) => (
<Button
key={`basic-data-table-${pageIndex}`}
onClick={() => table.setPageIndex(pageIndex)}
size="icon"
className={`w-7 h-7 hover:text-primary-foreground ${table.getState().pagination.pageIndex === pageIndex ? 'bg-default' : 'bg-default-100 text-default'}`}
>
{page + 1}
</Button>
))}
<Button
variant="outline"
size="icon"
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
className='w-8 h-8 border-transparent hover:bg-transparent'>
<ChevronRight className='w-5 h-5 text-default-900' />
</Button>
</div>
</div>
)
}
export default RecentOrderTable;

View File

@ -1,102 +0,0 @@
"use client";
import dynamic from "next/dynamic";
const Chart = dynamic(() => import("react-apexcharts"), { ssr: false });
import { colors } from "@/lib/colors";
import { useTheme } from "next-themes";
import { getLabel, getYAxisConfig } from "@/lib/appex-chart-options";
const VisitorsChart = ({ height = 350 }) => {
const { theme: mode } = useTheme();
const series = [
{
name: "Male",
data: [41, 64, 81, 60, 42, 42, 33, 23],
},
{
name: "Female",
data: [65, 46, 42, 25, 58, 63, 76, 43],
},
];
const options: any = {
chart: {
toolbar: {
show: false,
},
dropShadow: {
enabled: false,
blur: 8,
left: 1,
top: 1,
opacity: 0.5,
}
},
dataLabels: {
enabled: false,
},
tooltip: {
theme: mode === "dark" ? "dark" : "light",
},
colors: [colors.warning, colors.primary],
fill: {
opacity: [0.4, 0.4],
},
yaxis: getYAxisConfig(
mode === 'light' ? colors["default-600"] : colors["default-300"]
),
xaxis: {
categories: ["2019", "2020", "2021", "2017", "2018", "2015", "2014", "2013"],
labels: getLabel(mode === 'light' ? colors["default-600"] : colors["default-300"]),
axisBorder: {
show: false,
},
axisTicks: {
show: false,
}
},
legend: {
show: true,
fontSize: "14px",
fontFamily: "Inter",
labels: {
colors: mode === 'light' ? colors["default-600"] : colors["default-300"]
},
},
plotOptions: {
radar: {
size: undefined,
offsetX: 0,
offsetY: 0,
polygons: {
strokeColors: 'transparent',
strokeWidth: 0.5,
connectorColors: 'transparent',
},
},
},
stroke: {
width: 2,
},
markers: {
size: 0,
},
padding: {
top: 0,
right: 0,
bottom: 0,
left: 0,
}
};
return (
<Chart
options={options}
series={series}
type="radar"
height={height}
width={"100%"}
/>
);
};
export default VisitorsChart;

View File

@ -1,78 +0,0 @@
"use client";
import dynamic from "next/dynamic";
const Chart = dynamic(() => import("react-apexcharts"), { ssr: false });
import { useTheme } from "next-themes";
import {
getGridConfig,
getXAxisConfig,
getYAxisConfig,
} from "@/lib/appex-chart-options";
import { colors } from "@/lib/colors";
interface VisitorsReportChartProps {
height?: number;
seriesData?: number[];
}
const VisitorsReportChart = ({
height = 300 ,
seriesData =[90, 70, 85, 60, 80, 70, 90, 75, 60, 80]
}: VisitorsReportChartProps) => {
const { theme: mode } = useTheme();
const series = [
{
data:seriesData
},
];
const options: any = {
chart: {
toolbar: {
show: false,
},
},
dataLabels: {
enabled: false,
},
stroke: {
curve: "smooth",
width: 4,
},
colors: [colors.primary],
tooltip: {
theme: mode === "dark" ? "dark" : "light",
},
grid: getGridConfig(),
fill: {
type: "gradient",
colors: [colors.primary],
gradient: {
shadeIntensity: 1,
opacityFrom: 0.4,
opacityTo: 0.5,
stops: [50, 100, 0],
},
},
yaxis: getYAxisConfig(mode === 'light' ? colors["default-600"] : colors["default-300"]),
xaxis: getXAxisConfig(
mode === 'light' ? colors["default-600"] : colors["default-300"]
),
padding: {
top: 0,
right: 0,
bottom: 0,
left: 0,
},
};
return (
<Chart
options={options}
series={series}
type="area"
height={height}
width={"100%"}
/>
);
};
export default VisitorsReportChart;

File diff suppressed because one or more lines are too long

View File

@ -1,15 +0,0 @@
import { Metadata } from "next";
export const metadata:Metadata={
title: 'Ecommerce',
description: 'Ecommerce Description'
}
const Layout = ({children}: {children: React.ReactNode}) => {
return (
<>
{children}
</>
);
};
export default Layout;

View File

@ -1,184 +0,0 @@
import { StatusBlock } from "@/components/blocks/status-block";
import { WelcomeBlock } from "@/components/blocks/welcome-block";
import { Box, ShoppingCart, TrendingUp } from "lucide-react";
import Image from "next/image";
import RevinueBarChart from "@/components/revenue-bar-chart";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import DashboardDropdown from "@/components/dashboard-dropdown";
import OrdersBlock from "@/components/blocks/orders-block";
import EarningBlock from "@/components/blocks/earning-block";
import Customer from "./components/customer";
import RecentOrderTable from "./components/recent-order-table";
import VisitorsReportChart from "./components/visitors-report";
import VisitorsChart from "./components/visitors-chart";
import MostSales from "./components/most-sales";
import { products } from "./components/data";
import Product from "./components/product";
import { useTranslations } from "next-intl";
const EcommercePage = () => {
const t = useTranslations("EcommerceDashboard");
return (
<div className="space-y-5">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-5">
<WelcomeBlock>
<div className="max-w-[180px] relative z-10">
<h4 className="text-xl font-medium text-primary-foreground dark:text-default-900 mb-2">
<span className="block font-normal"> {t("widget_title")}</span>
<span className="block">Mr. Dianne Russell</span>
</h4>
<p className="text-sm text-primary-foreground dark:text-default-900 font-normal">
{t("widget_desc")}
</p>
</div>
<Image
src="/images/all-img/widget-bg-2.png"
width={400}
height={150}
priority
alt="Description of the image"
className="absolute top-0 start-0 w-full h-full object-cover rounded-md"
/>
</WelcomeBlock>
<StatusBlock
title={t("revenue_chart_title")}
total="3,564"
iconWrapperClass="bg-info/10"
chartColor="#00EBFF"
icon={<ShoppingCart className="w-5 h-5 text-info" />}
/>
<StatusBlock
title={t("sold_chart_title")}
total="564"
icon={<Box className="w-5 h-5 text-warning" />}
iconWrapperClass="bg-warning/10"
chartColor="#FB8F65"
/>
<StatusBlock
title={t("growth_chart_title")}
total="+5.0%"
icon={<TrendingUp className="w-5 h-5 text-primary" />}
iconWrapperClass="bg-primary/10"
chartColor="#2563eb"
/>
</div>
<div className="grid grid-cols-12 gap-5">
<div className="col-span-12 lg:col-span-8">
<Card>
<CardContent className="pt-5">
<RevinueBarChart height={420} />
</CardContent>
</Card>
</div>
<div className="col-span-12 lg:col-span-4">
<Card>
<CardHeader className="flex flex-row items-center gap-1">
<CardTitle className="flex-1">{t("statistics")}</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<div className="grid grid-cols-2 gap-5">
<div className="col-span-2 md:col-span-1">
<OrdersBlock
title={t("orders")}
total="123k"
chartColor="#f1595c"
className="border-none shadow-none bg-default-50 "
/>
</div>
<div className="col-span-2 md:col-span-1">
<OrdersBlock
title={t("profit")}
total="123k"
chartColor="#4669fa"
chartType="line"
percentageContent={
<span className="text-primary">+2.5%</span>
}
className="border-none shadow-none bg-default-50 col-span-2 md:col-span-1"
/>
</div>
<div className="col-span-2">
<EarningBlock
title={t("earnings")}
total="$12,335.00"
percentage="+08%"
className="col-span-2 border-none shadow-none bg-default-50"
/>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
<div className="grid lg:grid-cols-2 grid-cols-1 gap-5">
<Card>
<CardHeader className="flex flex-row items-center gap-1">
<CardTitle className="flex-1">{t("customer")}</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<Customer />
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center gap-1">
<CardTitle className="flex-1">
{t("recent_order_table_title")}
</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent className="px-0">
<RecentOrderTable />
</CardContent>
</Card>
</div>
<div className="grid grid-cols-12 gap-5">
<div className="lg:col-span-8 col-span-12">
<Card>
<CardHeader className="flex flex-row items-center gap-1">
<CardTitle className="flex-1">{t("visitors_report")}</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<VisitorsReportChart height={350} />
</CardContent>
</Card>
</div>
<div className="lg:col-span-4 col-span-12">
<Card>
<CardHeader className="flex flex-row items-center gap-1">
<CardTitle className="flex-1">
{t("Visitors_by_gender")}
</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<VisitorsChart />
</CardContent>
</Card>
</div>
</div>
<div className="grid lg:grid-cols-2 grid-cols-1 gap-5">
<MostSales />
<Card>
<CardHeader className="flex flex-row items-center gap-1">
<CardTitle className="flex-1">
{t("best_selling_products")}
</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<div className="grid md:grid-cols-3 grid-cols-1 gap-5">
{products.map((product, index) => (
<Product key={index} product={product} />
))}
</div>
</CardContent>
</Card>
</div>
</div>
);
};
export default EcommercePage;

View File

@ -1,218 +0,0 @@
export const meets = [
{
img: "/images/svg/sk.svg",
title: "Meeting with client",
date: "01 Nov 2021",
meet: "Zoom meeting",
},
{
img: "/images/svg/path.svg",
title: "Design meeting (team)",
date: "01 Nov 2021",
meet: "Skyp meeting",
},
{
img: "/images/svg/dc.svg",
title: "Background research",
date: "01 Nov 2021",
meet: "Google meeting",
},
{
img: "/images/svg/sk.svg",
title: "Meeting with client",
date: "01 Nov 2021",
meet: "Zoom meeting",
},
];
export const tasks = [
{
id: 1,
image: "/images/users/user-1.jpg",
title: "Amet minim mollit non deserunt ullam.",
},
{
id: 2,
image: "/images/users/user-2.jpg",
title: "Amet minim mollit non deserunt ullam.",
},
{
id: 3,
image: "/images/users/user-3.jpg",
title: "Amet minim mollit non deserunt ullam.",
},
{
id: 4,
image: "/images/users/user-4.jpg",
title: "Amet minim mollit non deserunt ullam.",
},
{
id: 5,
image: "/images/users/user-5.jpg",
title: "Amet minim mollit non deserunt ullam.",
},
{
id: 6,
image: "/images/users/user-6.jpg",
title: "Amet minim mollit non deserunt ullam.",
}]
export const messagesData = [
{
title: "Wade Warren",
desc: "Hi! How are you doing?.....",
active: true,
hasnotifaction: true,
notification_count: 1,
image: "/images/users/user-1.jpg"
},
{
title: "Savannah Nguyen",
desc: "Hi! How are you doing?.....",
active: false,
hasnotifaction: false,
image:"/images/users/user-2.jpg"
},
{
title: "Ralph Edwards",
desc: "Hi! How are you doing?.....",
active: false,
hasnotifaction: true,
notification_count: 8,
image: "/images/users/user-3.jpg"
},
{
title: "Cody Fisher",
desc: "Hi! How are you doing?.....",
active: true,
hasnotifaction: false,
image: "/images/users/user-4.jpg"
},
{
title: "Savannah Nguyen",
desc: "Hi! How are you doing?.....",
active: false,
hasnotifaction: false,
image: "/images/users/user-4.jpg"
}
];
export const activityList = [
{
title: "Project start date",
desc: "This parcel is paid for by the customer. Please contact the customer for any further information.",
date: "Sep 20, 2021 ",
time: "12:32 AM",
status: "ok",
},
{
title: "Project start date",
date: "Sep 20, 2021 ",
desc: "This parcel is paid for by the customer. Please contact the customer for any further information.",
time: "12:32 AM",
status: "ok",
},
{
title: "Project start date",
date: "Sep 20, 2021 ",
desc: "This parcel is paid for by the customer. Please contact the customer for any further information.",
time: "12:32 AM",
status: "ok",
},
{
title: "Project start date",
date: "Sep 20, 2021 ",
desc: "This parcel is paid for by the customer. Please contact the customer for any further information.",
time: "12:32 AM",
},
{
title: "Project start date",
date: "Sep 20, 2021 ",
desc: "This parcel is paid for by the customer. Please contact the customer for any further information.",
time: "12:32 AM",
},
];
export const teamData = [
{
customer: {
name: "Arlene McCoy",
image: "/images/users/user-1.jpg",
deg: "Ux designer",
},
status: "progress",
time: "42.5 hours",
chart: null,
action: null,
},
{
customer: {
name: "Arlene McCoy",
image: "/images/users/user-2.jpg",
deg: "Ux designer",
},
status: "complete",
time: "42.5 hours",
chart: null,
action: null,
},
{
customer: {
name: "Arlene McCoy",
image: "/images/users/user-3.jpg",
deg: "Ux designer",
},
status: "progress",
time: "42.5 hours",
chart: null,
action: null,
},
{
customer: {
name: "Arlene McCoy",
image: "/images/users/user-4.jpg",
deg: "Ux designer",
},
status: "complete",
time: "42.5 hours",
chart: null,
action: null
}
];
export const files = [
{
img: "/images/icon/file-1.svg",
title: "Dashboard.fig",
date: "06 June 2021 / 155MB",
},
{
img: "/images/icon/pdf-1.svg",
title: "Ecommerce.pdf",
date: "06 June 2021 / 155MB",
},
{
img: "/images/icon/zip-1.svg",
title: "Job portal_app.zip",
date: "06 June 2021 / 155MB",
},
{
img: "/images/icon/pdf-2.svg",
title: "Ecommerce.pdf",
date: "06 June 2021 / 155MB",
},
{
img: "/images/icon/scr-1.svg",
title: "Screenshot.jpg",
date: "06 June 2021 / 155MB",
}
];

View File

@ -1,15 +0,0 @@
import { Metadata } from "next";
export const metadata:Metadata={
title: 'Project Dashboard',
description: 'Project Dashboard Description'
}
const Layout = ({children}: {children: React.ReactNode}) => {
return (
<>
{children}
</>
);
};
export default Layout;

View File

@ -1,261 +0,0 @@
import ProgressBlock from "@/components/blocks/progress-block";
import DashboardDropdown from "@/components/dashboard-dropdown";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Icon } from "@/components/ui/icon";
import { BarChart } from "lucide-react";
import { meets, messagesData, tasks, activityList, teamData, files } from "./data";
import Image from "next/image";
import TaskItem from "@/components/project/task-item";
import MessageListItem from "@/components/project/message-list-item";
import ActivityItem from "@/components/project/activity";
import TeamTable from "@/components/project/team-table";
import NotesCalendar from "@/components/project/notes-calendar";
import DealsDistributionChart from "@/components/project/deals-distribution-chart";
import { useTranslations } from "next-intl";
const ProjectPage = () => {
const t = useTranslations("ProjectDashboard");
return (
<div className="space-y-5">
<div className="grid grid-cols-12 gap-5">
<div className="col-span-12 lg:col-span-8 space-y-5">
<Card>
<CardContent className="p-5">
<div className="grid grid-cols-12 gap-3">
<div className="col-span-12 lg:col-span-8 grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-4 gap-3">
<Card className="bg-info/20 shadow-none border-none">
<CardContent className=" p-4 text-center">
<div className="mx-auto h-10 w-10 rounded-full flex items-center justify-center bg-white mb-4">
<BarChart className=" h-6 w-6 text-info" />
</div>
<div className="block text-sm text-default-600 font-medium mb-1.5">
{" "}
{t("total_task")}
</div>
<div className="text-2xl text-default-900 font-medium">
64
</div>
</CardContent>
</Card>
<Card className="bg-warning/20 shadow-none border-none">
<CardContent className=" p-4 text-center">
<div className="mx-auto h-10 w-10 rounded-full flex items-center justify-center bg-white mb-4">
<Icon
className="w-6 h-6 text-warning"
icon="heroicons:chart-pie"
/>
</div>
<div className="block text-sm text-default-600 font-medium mb-1.5">
{t("completed")}
</div>
<div className="text-2xl text-default-900 font-medium">
45
</div>
</CardContent>
</Card>
<Card className="bg-primary/20 shadow-none border-none">
<CardContent className=" p-4 text-center">
<div className="mx-auto h-10 w-10 rounded-full flex items-center justify-center bg-white mb-4">
<Icon
className="w-6 h-6 text-primary"
icon="heroicons:clock"
/>
</div>
<div className="block text-sm text-default-600 font-medium mb-1.5">
{t("hours")}
</div>
<div className="text-2xl text-default-900 font-medium">
190
</div>
</CardContent>
</Card>
<Card className="bg-success/20 shadow-none border-none">
<CardContent className="p-4 text-center">
<div className="mx-auto h-10 w-10 rounded-full flex items-center justify-center bg-white mb-4">
<Icon
className="w-6 h-6 text-success"
icon="heroicons:calculator"
/>
</div>
<div className="block text-sm text-default-600 font-medium mb-1.5">
{t("spendings")}
</div>
<div className="text-2xl text-default-900 font-medium">
$3,564
</div>
</CardContent>
</Card>
</div>
<div className="col-span-12 lg:col-span-4">
<ProgressBlock
title={t("progress")}
height={113}
className="border-none shadow-none"
chartType="pie"
/>
</div>
</div>
</CardContent>
</Card>
<Card>
<CardHeader className="flex-row justify-between">
<CardTitle>{t("deal_distribution_by_stage")}</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<DealsDistributionChart height={310} />
</CardContent>
</Card>
</div>
<div className="col-span-12 lg:col-span-4">
<Card>
<CardHeader>
<CardTitle>{t("notes")}</CardTitle>
</CardHeader>
<CardContent className="px-2">
<NotesCalendar />
<ul className="divide-y divide-default-100 dark:divide-default-300">
{meets.map((item, i) => (
<li key={i} className=" py-2.5 px-3">
<div className="flex gap-2">
<div className="flex-1 flex gap-2.5">
<div className="flex-none">
<div className="h-8 w-8">
<Image
src={item.img}
alt=""
className="w-full h-full "
width={32}
height={32}
/>
</div>
</div>
<div className="flex-1">
<div className="text-default-600 text-sm mb-1 font-medium">
{item.title}
</div>
<div className="flex gap-1 font-normal text-xs text-default-500">
<div className="text-base">
<Icon icon="heroicons-outline:video-camera" />
</div>
{item.meet}
</div>
</div>
</div>
<div className="flex-none text-xs text-default-600">
{item.date}
</div>
</div>
</li>
))}
</ul>
</CardContent>
</Card>
</div>
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-5">
<Card>
<CardHeader className="flex-row items-center justify-between">
<CardTitle>{t("task_list")}</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent className="p-0">
<ul className="divide-y divide-default-100 dark:divide-default-300">
{tasks.map((task, index) => (
<TaskItem key={index} task={task} />
))}
</ul>
</CardContent>
</Card>
<Card>
<CardHeader className="flex-row items-center justify-between">
<CardTitle>{t("messages")}</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent className="p-0">
<ul className="divide-y divide-default-100 dark:divide-default-300">
{messagesData.map((message, index) => (
<MessageListItem message={message} key={index} />
))}
</ul>
</CardContent>
</Card>
<Card>
<CardHeader className="flex-row items-center justify-between">
<CardTitle>{t("activity")}</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent className="p-0">
<ul className="relative before:absolute before:start-6 before:top-3.5 before:w-[1px] before:h-[80%] before:bg-default-200 dark:before:bg-default-300">
{activityList.map((activity, index) => (
<ActivityItem activity={activity} key={index} />
))}
</ul>
</CardContent>
</Card>
</div>
<div className="grid grid-cols-12 gap-5">
<div className="col-span-12 lg:col-span-8">
<Card>
<CardHeader className="flex-row items-center justify-between">
<CardTitle>{t("team_members")}</CardTitle>
</CardHeader>
<CardContent className="p-0">
<TeamTable data={teamData} />
</CardContent>
</Card>
</div>
<div className="col-span-12 lg:col-span-4">
<Card>
<CardHeader className="flex-row items-center justify-between">
<CardTitle>{t("files")}</CardTitle>
<DashboardDropdown />
</CardHeader>
<CardContent>
<ul className="divide-y divide-default-100 dark:divide-default-300">
{files.map((item, i) => (
<li key={i} className="py-3">
<div className="flex items-center gap-2">
<div className="flex-1 flex gap-2">
<div className="flex-none">
<div className="h-8 w-8">
<Image
src={item.img}
alt=""
width={32}
height={32}
className=" w-full h-full object-cover rounded-full border hover:border-primary-foreground border-transparent"
/>
</div>
</div>
<div className="flex-1">
<div className="text-default-600 text-sm">
{item.title}
</div>
<div className="font-normal text-xs text-default-500 mt-1">
{item.date}
</div>
</div>
</div>
<div className="flex-none">
<button
type="button"
className="text-xs text-default-900 "
>
{t("download")}
</button>
</div>
</div>
</li>
))}
</ul>
</CardContent>
</Card>
</div>
</div>
</div>
);
};
export default ProjectPage;

View File

@ -1,38 +1,38 @@
'use client'
"use client";
import React from "react";
import DashCodeLogo from "./dascode-logo";
import { Link } from '@/i18n/routing';
import { Link } from "@/i18n/routing";
import { useConfig } from "@/hooks/use-config";
import { useMenuHoverConfig } from "@/hooks/use-menu-hover";
import { useMediaQuery } from "@/hooks/use-media-query";
const Logo = () => {
const [config] = useConfig()
const [hoverConfig] = useMenuHoverConfig();
const { hovered } = hoverConfig
const isDesktop = useMediaQuery('(min-width: 1280px)');
if (config.sidebar === 'compact') {
return <Link href="/dashboard/analytics" className="flex gap-2 items-center justify-center ">
<DashCodeLogo className=" text-default-900 h-8 w-8 [&>path:nth-child(3)]:text-background [&>path:nth-child(2)]:text-background" />
</Link>
}
if (config.sidebar === 'two-column' || !isDesktop) return null
const [config] = useConfig();
const [hoverConfig] = useMenuHoverConfig();
const { hovered } = hoverConfig;
const isDesktop = useMediaQuery("(min-width: 1280px)");
if (config.sidebar === "compact") {
return (
<Link href="/dashboard/analytics" className="flex gap-2 items-center ">
<DashCodeLogo className=" text-default-900 h-8 w-8 [&>path:nth-child(3)]:text-background [&>path:nth-child(2)]:text-background" />
{(!config?.collapsed || hovered) && (
<h1 className="text-xl font-semibold text-default-900 ">
DashCode
</h1>
)}
</Link>
<Link
href="/dashboard/analytics"
className="flex gap-2 items-center justify-center "
>
<DashCodeLogo className=" text-default-900 h-8 w-8 [&>path:nth-child(3)]:text-background [&>path:nth-child(2)]:text-background" />
</Link>
);
}
if (config.sidebar === "two-column" || !isDesktop) return null;
return (
<Link href="/dashboard/analytics" className="flex gap-2 items-center ">
{/* <DashCodeLogo className=" text-default-900 h-8 w-8 [&>path:nth-child(3)]:text-background [&>path:nth-child(2)]:text-background" />
{(!config?.collapsed || hovered) && (
<h1 className="text-xl font-semibold text-default-900 ">D</h1>
)} */}
<img src="/../images/all-img/mediahub-logo.png" alt="logo" width={150} />
</Link>
);
};
export default Logo;

View File

@ -1,22 +1,32 @@
"use client";
import React from "react";
import DateRangePicker from "@/components/date-range-picker";
import { usePathname } from "@/components/navigation";
import { cn } from "@/lib/utils";
'use client'
import React from 'react'
import DateRangePicker from '@/components/date-range-picker'
import { usePathname } from '@/components/navigation'
import { cn } from "@/lib/utils"
const PageTitle = ({
title,
className,
}: {
title?: string;
className?: string;
}) => {
const pathname = usePathname();
const name = pathname?.split("/").slice(1).join(" ");
const PageTitle = ({ title, className }: { title?: string, className?: string }) => {
const pathname = usePathname();
const name = pathname?.split('/').slice(1).join(' ');
return (
<div
className={cn(
"flex flex-wrap gap-4 items-center justify-between",
className
)}
>
<div className="text-2xl font-medium text-default-800 capitalize">
Dashboard
</div>
<DateRangePicker />
</div>
);
};
return (
<div className={cn('flex flex-wrap gap-4 items-center justify-between', className)}>
<div className="text-2xl font-medium text-default-800 capitalize">
{title ? title : name ? name : null}
</div>
<DateRangePicker />
</div>
)
}
export default PageTitle
export default PageTitle;

View File

@ -1,33 +1,32 @@
'use client'
import React from 'react'
import { Link } from '@/components/navigation'
import DashCodeLogo from "@/components/dascode-logo"
import { useConfig } from '@/hooks/use-config'
import { useMediaQuery } from '@/hooks/use-media-query'
"use client";
import React from "react";
import { Link } from "@/components/navigation";
import DashCodeLogo from "@/components/dascode-logo";
import { useConfig } from "@/hooks/use-config";
import { useMediaQuery } from "@/hooks/use-media-query";
const HeaderLogo = () => {
const [config] = useConfig();
const [config] = useConfig();
const isDesktop = useMediaQuery('(min-width: 1280px)');
const isDesktop = useMediaQuery("(min-width: 1280px)");
return (
config.layout === 'horizontal' ? (
<Link href="/dashboard/analytics" className="flex gap-2 items-center ">
<DashCodeLogo className=" text-default-900 h-8 w-8 [&>path:nth-child(3)]:text-background [&>path:nth-child(2)]:text-background" />
<h1 className="text-xl font-semibold text-default-900 lg:block hidden ">
DashCode
</h1>
</Link>
) :
!isDesktop && (
<Link href="/dashboard/analytics" className="flex gap-2 items-center ">
<DashCodeLogo className=" text-default-900 h-8 w-8 [&>path:nth-child(3)]:text-background [&>path:nth-child(2)]:text-background" />
<h1 className="text-xl font-semibold text-default-900 lg:block hidden ">
DashCode
</h1>
</Link>
)
return config.layout === "horizontal" ? (
<Link href="/dashboard/analytics" className="flex gap-2 items-center ">
<DashCodeLogo className=" text-default-900 h-8 w-8 [&>path:nth-child(3)]:text-background [&>path:nth-child(2)]:text-background" />
<h1 className="text-xl font-semibold text-default-900 lg:block hidden ">
DashCode
</h1>
</Link>
) : (
!isDesktop && (
<Link href="/dashboard/analytics" className="flex gap-2 items-center ">
<DashCodeLogo className=" text-default-900 h-8 w-8 [&>path:nth-child(3)]:text-background [&>path:nth-child(2)]:text-background" />
<h1 className="text-xl font-semibold text-default-900 lg:block hidden ">
DashCode
</h1>
</Link>
)
}
);
};
export default HeaderLogo
export default HeaderLogo;

234
config/api.ts Normal file
View File

@ -0,0 +1,234 @@
"use client";
import axios from "axios";
import Cookies from "js-cookie";
import qs from "qs";
import axiosInstance from "./axiosInstance";
import axiosInstanceJson from "./axiosInstanceJson";
import axiosInterceptor from "./axiosInterceptor";
import { data } from "@/app/[locale]/(protected)/charts/rechart/charts-rechart-bar/data";
import { url } from "inspector";
const baseURL = "https://netidhub.com/api/";
const tokenAuth = Cookies.get("access_token")
? Cookies.get("access_token")
: null;
export async function postAPI(url: any, data: any) {
const headers = {
Authorization: `Bearer ${tokenAuth}`,
};
const response = await axiosInstance
.post(url, qs.stringify(data), { headers })
.catch((error) => error.response);
if (response?.status > 300) {
return {
error: true,
message: response?.data.error_description,
data: null,
};
}
return {
error: false,
message: "success",
data: response?.data,
};
}
export async function getAPI(url: any, token: any) {
const headers = {
Authorization: `Bearer ${token || tokenAuth}`,
};
const response = await axios
.get(baseURL + url, { headers })
.catch((error) => error.response);
if (response?.status > 300) {
return {
error: true,
message: response?.data?.error_description,
data: null,
};
}
return {
error: false,
message: "success",
data: response?.data,
};
}
export async function postAPIWithJson(url: any, data: any, token: any) {
const headers = {
Authorization: `Bearer ${token || tokenAuth}`,
};
const response = await axiosInstanceJson
.post(url, data, { headers })
.catch((error) => error.response);
if (response?.status > 300) {
return {
error: true,
message: response?.data?.message,
data: null,
};
}
return {
error: false,
message: "success",
data: response?.data,
};
}
export async function deleteAPIWithJson(url: any) {
const response = await axiosInstanceJson
.delete(url)
.catch((error) => error.response);
if (response?.status > 300) {
return {
error: true,
message: response?.data?.message,
data: null,
};
}
return {
error: false,
message: "success",
data: response?.data,
};
}
export async function getAPIInterceptor(url: any) {
const response = await axiosInterceptor
.get(url)
.catch((error) => error.response);
if (response?.status == 401) {
Object.keys(Cookies.get()).forEach((cookieName) => {
Cookies.remove(cookieName);
});
window.location.href = "/";
} else if (response?.status > 300 && response?.status != 401) {
return {
error: true,
message: response?.data?.message,
data: null,
};
} else if (response?.data.success) {
return {
error: false,
message: "success",
data: response?.data,
};
}
return {
error: true,
message: response?.data?.message || null,
data: null,
};
}
export async function postAPIInterceptor(url: any, data: any) {
const response = await axiosInterceptor
.post(url, data)
.catch((error) => error.response);
if (response?.status == 401) {
Object.keys(Cookies.get()).forEach((cookieName) => {
Cookies.remove(cookieName);
});
window.location.href = "/";
} else if (response?.status > 300 && response?.status != 401) {
return {
error: true,
message: response?.data?.message,
data: null,
};
} else if (response?.data.success) {
return {
error: false,
message: "success",
data: response?.data,
};
}
return {
error: true,
message: response?.data.message,
data: null,
};
}
export async function deleteAPIInterceptor(url: any, data: any) {
const response = await axiosInterceptor
.delete(url, { data })
.catch((error) => error.response);
if (response?.status == 401) {
Object.keys(Cookies.get()).forEach((cookieName) => {
Cookies.remove(cookieName);
});
window.location.href = "/";
} else if (response?.status > 300 && response?.status != 401) {
return {
error: true,
message: response?.data?.message,
data: null,
};
} else if (response?.data.success) {
return {
error: false,
message: "success",
data: response?.data,
};
}
return {
error: true,
message: response?.data?.message,
data: null,
};
}
export async function getAPIInterceptorProfile(url: any) {
const response = await axiosInterceptor
.get(url)
.catch((error) => error.response);
if (response?.status > 300) {
return {
error: true,
message: response?.data?.message,
data: null,
};
}
return {
error: false,
message: response?.data?.message,
data: response?.data,
};
}
// export async function postFileApiInterceptor(url: any, data: any) {
// const response = await axiosInterceptor
// .post(url, data, {
// onUploadProgress: (progressEvent) => {
// const percentage = Math.round(
// (progressEvent.loaded * 100) / progressEvent.total
// );
// console.log(percentage);
// },
// })
// .catch((error) => error.response);
// if (response?.status > 300) {
// return {
// error: true,
// message: response?.data?.message,
// data: null,
// };
// }
// if (response?.data.success) {
// return {
// error: false,
// message: "success",
// data: response?.data,
// };
// }
// return {
// error: true,
// message: response?.data.message,
// data: null,
// };
// }

14
config/axiosInstance.ts Normal file
View File

@ -0,0 +1,14 @@
"use client";
import axios from "axios";
const baseURL = "https://netidhub.com/api/";
const axiosInstance = axios.create({
baseURL,
headers: {
"content-type": "application/x-www-form-urlencoded",
},
withCredentials: false,
});
export default axiosInstance;

View File

@ -0,0 +1,13 @@
"use client";
import axios from "axios";
const baseURL = "https://netidhub.com/api/";
const axiosInstanceJson = axios.create({
baseURL,
headers: {
"content-type": "application/json",
},
});
export default axiosInstanceJson;

View File

@ -0,0 +1,59 @@
"use client";
import axios from "axios";
import Cookies from "js-cookie";
import qs from "qs";
const baseURL = "https://netidhub.com/api/";
const tokenAuth = Cookies.get("access_token")
? Cookies.get("access_token")
: null;
const expired = Cookies.get("time_refresh")
? Cookies.get("time_refresh")
: null;
const axiosInterceptor = axios.create({
baseURL,
headers: {
Authorization: `Bearer ${tokenAuth}`,
},
});
axiosInterceptor.interceptors.request.use(async (req) => {
const time = new Date();
const expiredValue = Cookies.get("time_refresh"); // Assuming 'time_refresh' contains `expired`
if (expiredValue) {
const expired = new Date(expiredValue); // Ensure valid Date object
if (time.getTime() >= expired.getTime()) {
const url = `${baseURL}/signin`;
const data = {
grant_type: "refresh_token",
client_id: "mediahub-app",
refresh_token: Cookies.get("refresh_token") || "", // Fallback to empty string if undefined
};
const response = await axios
.post(url, qs.stringify(data))
.catch((error) => error.response);
if (response?.status === 401) {
Object.keys(Cookies.get() || {}).forEach((cookieName) => {
Cookies.remove(cookieName);
});
window.location.href = "/";
} else {
const { access_token, refresh_token } = response?.data || {};
const dateTime = new Date();
const newTime = dateTime.getTime() + 10 * 60 * 1000;
Cookies.set("access_token", access_token, { expires: 1 });
Cookies.set("refresh_token", refresh_token, { expires: 1 });
Cookies.set("time_refresh", new Date(newTime).toISOString(), {
expires: 1,
});
}
}
}
return req;
});
export default axiosInterceptor;

View File

@ -51,48 +51,48 @@ export function getMenuList(pathname: string, t: any): Group[] {
{
id: "content",
href: "/content/image",
label: t("konten"),
label: "konten",
active: pathname.includes("/content"),
icon: "line-md:youtube",
submenus: [
{
href: "/content/image",
label: t("image"),
label: "image",
active: pathname === "/content/image",
icon: "ic:outline-image",
children: [],
},
{
href: "/content/audio-visual",
label: t("audio visual"),
label: "audio visual",
active: pathname === "/content/audio-visual",
icon: "line-md:youtube",
children: [],
},
{
href: "/content/teks",
label: t("text"),
label: "teks",
active: pathname === "/content/teks",
icon: "heroicons:document",
children: [],
},
{
href: "/content/audio",
label: t("audio"),
label: "audio",
active: pathname === "/content/audio",
icon: "heroicons:share",
children: [],
},
{
href: "/content/spit",
label: t("spit"),
label: "spit",
active: pathname === "/content/spit",
icon: "heroicons:credit-card",
children: [],
},
{
href: "/content/nulis-ai",
label: t("nulis ai"),
label: "nulis ai",
active: pathname === "/content/nulisai",
icon: "heroicons:credit-card",
children: [],
@ -108,7 +108,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
{
id: "agenda-setting",
href: "/agenda-setting",
label: t("agenda setting"),
label: "agenda setting",
active: pathname.includes("/agenda-setting"),
icon: "iconoir:journal-page",
submenus: [],
@ -122,20 +122,20 @@ export function getMenuList(pathname: string, t: any): Group[] {
{
id: "planning",
href: "/planning",
label: t("perencanaan"),
label: "perencanaan",
active: pathname.includes("/planning"),
icon: "pajamas:planning",
submenus: [
{
href: "/planning/mediahub",
label: t("mediaHub"),
label: "mediaHub",
active: pathname === "/planning/mediahub",
icon: "heroicons:arrow-trending-up",
children: [],
},
{
href: "/planning/medsos-mediahub",
label: t("medsos mediahub"),
label: "medsos mediahub",
active: pathname === "/planning/medsos-mediahub",
icon: "heroicons:shopping-cart",
children: [],
@ -151,7 +151,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
{
id: "task",
href: "/task",
label: t("penugasan"),
label: "penugasan",
active: pathname.includes("/task"),
icon: "fluent:clipboard-task-add-24-regular",
submenus: [],
@ -165,27 +165,27 @@ export function getMenuList(pathname: string, t: any): Group[] {
{
id: "schedule",
href: "/schedule",
label: t("schedule"),
label: "schedule",
active: pathname.includes("/schedule"),
icon: "uil:schedule",
submenus: [
{
href: "/schedule/press-conference",
label: t("konfesensi pers"),
label: "konfesensi pers",
active: pathname === "/schedule/press-conference",
icon: "heroicons:arrow-trending-up",
children: [],
},
{
href: "/schedule/event",
label: t("event"),
label: "event",
active: pathname === "/schedule/event",
icon: "heroicons:shopping-cart",
children: [],
},
{
href: "/schedule/press-release",
label: t("pers rilis"),
label: "pers rilis",
active: pathname === "/schedule/press-release",
icon: "heroicons:shopping-cart",
children: [],
@ -201,7 +201,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
{
id: "blog",
href: "/blog",
label: t("indeks"),
label: "indeks",
active: pathname.includes("/blog"),
icon: "fluent:clipboard-text-32-regular",
submenus: [],
@ -215,7 +215,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
{
id: "curatedcontent",
href: "/curated-content",
label: t("kurasi konten"),
label: "kurasi konten",
active: pathname.includes("/curated-content"),
icon: "pixelarticons:calendar-text",
submenus: [],
@ -229,7 +229,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
{
id: "communication",
href: "/communication",
label: t("komunikasi"),
label: "komunikasi",
active: pathname.includes("/communication"),
icon: "token:chat",
submenus: [],
@ -243,7 +243,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
{
id: "contest",
href: "/contest",
label: t("lomba"),
label: "lomba",
active: pathname.includes("/contest"),
icon: "ic:outline-emoji-events",
submenus: [],

938
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -53,14 +53,18 @@
"@south-paw/react-vector-maps": "^3.2.0",
"@tanstack/react-table": "^8.19.2",
"@types/cleave.js": "^1.4.12",
"@types/js-cookie": "^3.0.6",
"@types/qs": "^6.9.17",
"@types/react-syntax-highlighter": "^15.5.13",
"@vercel/analytics": "^1.3.1",
"apexcharts": "^3.49.2",
"axios": "^1.7.8",
"chart.js": "^4.4.3",
"class-variance-authority": "^0.7.0",
"cleave.js": "^1.6.0",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
"cookie": "^1.0.2",
"date-fns": "^3.6.0",
"dayjs": "^1.11.11",
"embla-carousel-autoplay": "^8.1.3",
@ -71,6 +75,7 @@
"google-map-react": "^2.2.1",
"input-otp": "^1.2.4",
"jotai": "^2.9.3",
"js-cookie": "^3.0.5",
"leaflet": "^1.9.4",
"lucide-react": "^0.390.0",
"moment": "^2.30.1",
@ -80,6 +85,7 @@
"next-themes": "^0.3.0",
"nextra": "^2.13.4",
"nextra-theme-docs": "^2.13.4",
"qs": "^6.13.1",
"quill": "^2.0.2",
"react": "^18",
"react-apexcharts": "^1.4.1",

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 KiB

77
service/media.ts Normal file
View File

@ -0,0 +1,77 @@
import {
deleteAPIInterceptor,
getAPI,
getAPIInterceptor,
postAPIInterceptor,
} from "../config/api";
export async function listDataMedia(
page: any,
limit: any,
search: any,
categoryFilter: any,
statusFilter: any
) {
const name = search || "";
const url = `media/list?isForAdmin=true&title=${name}&enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=1&categoryId=${categoryFilter}&statusId=${statusFilter}`;
return getAPIInterceptor({ url });
}
export async function listDataVideo(
isForSelf: any,
isApproval: any,
page: any,
limit: any,
search: any,
categoryFilter: any,
statusFilter: any,
needApprovalFromLevel: any,
creator: any,
source: any,
startDate: any,
endDate: any
) {
const name = search || "";
const url = `media/list?title=${name}&enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=2&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}`;
return getAPIInterceptor({ url });
}
export async function listDataImage(
isForSelf: any,
isApproval: any,
page: any,
limit: any,
search: any,
categoryFilter: any,
statusFilter: any,
needApprovalFromLevel: any,
creator: any,
source: any,
startDate: any,
endDate: any
) {
const name = search || "";
const url = `media/list?title=${name}&enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=1&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}`;
return getAPIInterceptor({ url });
}
export async function listDataAll(
isForSelf: any,
isApproval: any,
page: any,
limit: any,
search: any,
fileTypeFilter: any,
statusFilter: any,
startDate: any,
endDate: any,
needApprovalFromLevel: any
) {
const name = search || "";
const url = `media/list?title=${name}&enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&isForSelf=${isForSelf}&isApproval=${isApproval}&typeId=${fileTypeFilter}&statusId=${statusFilter}&startDate=${
startDate == undefined ? "" : startDate
}&endDate=${
endDate == undefined ? "" : endDate
}&needApprovalFromLevel=${needApprovalFromLevel}`;
return getAPIInterceptor({ url });
}

View File

@ -1,7 +1,6 @@
import React from 'react'
import { DocsThemeConfig } from 'nextra-theme-docs'
import DashCodeLogo from '@/components/dascode-logo';
import React from "react";
import { DocsThemeConfig } from "nextra-theme-docs";
import DashCodeLogo from "@/components/dascode-logo";
const config: DocsThemeConfig = {
logo: (
<span className=" inline-flex gap-2.5 items-center">
@ -34,9 +33,9 @@ const config: DocsThemeConfig = {
themeSwitch: {
useOptions() {
return {
light: 'Light',
dark: 'Dark',
system: 'System', // Add this line
light: "Light",
dark: "Dark",
system: "System", // Add this line
};
},
},
@ -47,4 +46,4 @@ const config: DocsThemeConfig = {
},
};
export default config
export default config;