feat:faq fixing, tickting table fixing
This commit is contained in:
parent
525f158388
commit
c314be8cc8
|
|
@ -1,76 +1,101 @@
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import {
|
import { ColumnDef } from "@tanstack/react-table";
|
||||||
ColumnDef,
|
|
||||||
} from "@tanstack/react-table";
|
import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react";
|
||||||
|
|
||||||
import {
|
|
||||||
Eye,
|
|
||||||
MoreVertical,
|
|
||||||
SquarePen,
|
|
||||||
Trash2,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
DropdownMenuItem,
|
|
||||||
} from "@/components/ui/dropdown-menu";
|
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
|
||||||
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
import { error } from "@/config/swal";
|
||||||
|
import { deleteCategory, deleteDataFAQ } from "@/service/settings/settings";
|
||||||
|
import { useToast } from "@/components/ui/use-toast";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Menubar,
|
||||||
|
MenubarContent,
|
||||||
|
MenubarMenu,
|
||||||
|
MenubarTrigger,
|
||||||
|
} from "@/components/ui/menubar";
|
||||||
|
import { htmlToString } from "@/utils/globals";
|
||||||
|
import EditSpvFAQModal from "./edit";
|
||||||
|
|
||||||
const columns: ColumnDef<any>[] = [
|
const columns: ColumnDef<any>[] = [
|
||||||
{
|
{
|
||||||
accessorKey: "no",
|
accessorKey: "no",
|
||||||
header: "No",
|
header: "No",
|
||||||
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
accessorKey: "question",
|
accessorKey: "question",
|
||||||
header: "Question",
|
header: "Pertanyaan",
|
||||||
cell: ({ row }) => <span>{row.getValue("question")}</span>,
|
cell: ({ row }) => (
|
||||||
|
<span className="normal-case">
|
||||||
|
{htmlToString(row.getValue("question"))}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "answer",
|
accessorKey: "answer",
|
||||||
header: "Answer",
|
header: "Answer",
|
||||||
cell: ({ row }) => <span>{row.getValue("answer")}</span>,
|
cell: ({ row }) => (
|
||||||
|
<span className="normal-case">
|
||||||
|
{htmlToString(row.getValue("answer"))}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
id: "actions",
|
id: "actions",
|
||||||
accessorKey: "action",
|
accessorKey: "action",
|
||||||
header: "Actions",
|
header: "Actions",
|
||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
|
const router = useRouter();
|
||||||
|
const { toast } = useToast();
|
||||||
|
|
||||||
|
const faqDelete = async (id: string) => {
|
||||||
|
const response = await deleteDataFAQ(id);
|
||||||
|
console.log(response);
|
||||||
|
if (response?.error) {
|
||||||
|
error(response.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
toast({
|
||||||
|
title: "Sukses",
|
||||||
|
description: "Berhasil Delete",
|
||||||
|
});
|
||||||
|
router.push("/supervisor/faq?dataChange=true");
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<DropdownMenu>
|
<Menubar className="border-none">
|
||||||
<DropdownMenuTrigger asChild>
|
<MenubarMenu>
|
||||||
<Button
|
<MenubarTrigger>
|
||||||
size="icon"
|
<Button
|
||||||
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
|
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" />
|
<MoreVertical className="h-4 w-4 text-default-800" />
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</MenubarTrigger>
|
||||||
<DropdownMenuContent className="p-0" align="end">
|
<MenubarContent className="flex flex-col gap-2 justify-center items-start p-4">
|
||||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
<EditSpvFAQModal id={row.original.id} isDetail={true} />
|
||||||
<Eye className="w-4 h-4 me-1.5" />
|
|
||||||
View
|
<EditSpvFAQModal id={row.original.id} isDetail={false} />
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
<a
|
||||||
<SquarePen className="w-4 h-4 me-1.5" />
|
onClick={() => faqDelete(row.original.id)}
|
||||||
Edit
|
className="hover:underline cursor-pointer hover:text-destructive"
|
||||||
</DropdownMenuItem>
|
>
|
||||||
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
|
Delete
|
||||||
<Trash2 className="w-4 h-4 me-1.5" />
|
</a>
|
||||||
Delete
|
</MenubarContent>
|
||||||
</DropdownMenuItem>
|
</MenubarMenu>
|
||||||
</DropdownMenuContent>
|
</Menubar>
|
||||||
</DropdownMenu>
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default columns;
|
export default columns;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,202 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from "@/components/ui/form";
|
||||||
|
import { useRouter } from "@/i18n/routing";
|
||||||
|
|
||||||
|
import {
|
||||||
|
getUserRoles,
|
||||||
|
postCategory,
|
||||||
|
postDataFAQ,
|
||||||
|
} from "@/service/settings/settings";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
||||||
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
import { close, error, loading } from "@/config/swal";
|
||||||
|
import { useToast } from "@/components/ui/use-toast";
|
||||||
|
import { stringify } from "querystring";
|
||||||
|
|
||||||
|
const FormSchema = z.object({
|
||||||
|
answer: z.string({
|
||||||
|
required_error: "Required",
|
||||||
|
}),
|
||||||
|
question: z.string({
|
||||||
|
required_error: "Required",
|
||||||
|
}),
|
||||||
|
publishTo: z.string({
|
||||||
|
required_error: "Required",
|
||||||
|
}),
|
||||||
|
|
||||||
|
// publishTo: z.array(z.string()).refine((value) => value.some((item) => item), {
|
||||||
|
// message: "Required",
|
||||||
|
// }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const publishToList = [
|
||||||
|
{
|
||||||
|
id: "mabes",
|
||||||
|
name: "Nasional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "polda",
|
||||||
|
name: "Polda",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "satker",
|
||||||
|
name: "Satker",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "internasional",
|
||||||
|
name: "Internasional",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function CreateSpvFAQModal() {
|
||||||
|
const router = useRouter();
|
||||||
|
const { toast } = useToast();
|
||||||
|
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const form = useForm<z.infer<typeof FormSchema>>({
|
||||||
|
resolver: zodResolver(FormSchema),
|
||||||
|
defaultValues: { publishTo: "wilayah" },
|
||||||
|
});
|
||||||
|
|
||||||
|
const target = form.watch("publishTo");
|
||||||
|
const isAllTargetChecked = publishToList.every((item) =>
|
||||||
|
target?.includes(item.id)
|
||||||
|
);
|
||||||
|
|
||||||
|
const onSubmit = async (data: z.infer<typeof FormSchema>) => {
|
||||||
|
const request = {
|
||||||
|
question: data.question,
|
||||||
|
answer: data.answer,
|
||||||
|
isInternational: data.publishTo === "wilayah" ? false : true,
|
||||||
|
isActive: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await postDataFAQ(request);
|
||||||
|
close();
|
||||||
|
if (response?.error) {
|
||||||
|
toast({ title: stringify(response.message), variant: "destructive" });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
toast({
|
||||||
|
title: "Succes",
|
||||||
|
description: "FAQ berhasil dibuat",
|
||||||
|
});
|
||||||
|
router.push("/supervisor/faq?dataChange=true");
|
||||||
|
setIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<Button color="primary" size="md">
|
||||||
|
Tambah FAQ
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent size="md">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Tambah FAQ</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<Form {...form}>
|
||||||
|
<form
|
||||||
|
onSubmit={form.handleSubmit(onSubmit)}
|
||||||
|
className="space-y-3 bg-white rounded-sm"
|
||||||
|
>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="publishTo"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="space-y-3">
|
||||||
|
<FormLabel>Wilayah Publish</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<RadioGroup
|
||||||
|
onValueChange={field.onChange}
|
||||||
|
value={field.value}
|
||||||
|
className="flex flex-row space-x-1"
|
||||||
|
>
|
||||||
|
<FormItem className="flex items-center space-x-3 space-y-0">
|
||||||
|
<FormControl>
|
||||||
|
<RadioGroupItem value="wilayah" />
|
||||||
|
</FormControl>
|
||||||
|
<FormLabel className="font-normal">Wilayah</FormLabel>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem className="flex items-center space-x-3 space-y-0">
|
||||||
|
<FormControl>
|
||||||
|
<RadioGroupItem value="international" />
|
||||||
|
</FormControl>
|
||||||
|
<FormLabel className="font-normal">
|
||||||
|
Internasional
|
||||||
|
</FormLabel>
|
||||||
|
</FormItem>
|
||||||
|
</RadioGroup>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="question"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Pertanyaan</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Textarea placeholder="Masukkan pertanyaan" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="answer"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Jawaban</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Textarea placeholder="Masukkan jawaban" {...field} />
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
color="primary"
|
||||||
|
size="md"
|
||||||
|
className="text-xs"
|
||||||
|
>
|
||||||
|
Tambah FAQ
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,237 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from "@/components/ui/form";
|
||||||
|
import { useRouter } from "@/i18n/routing";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import {
|
||||||
|
detailDataFAQ,
|
||||||
|
getUserRoles,
|
||||||
|
postCategory,
|
||||||
|
postDataFAQ,
|
||||||
|
} from "@/service/settings/settings";
|
||||||
|
import { Fragment, useEffect, useState } from "react";
|
||||||
|
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
||||||
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
import { close, error, loading } from "@/config/swal";
|
||||||
|
import { useToast } from "@/components/ui/use-toast";
|
||||||
|
import { stringify } from "querystring";
|
||||||
|
import { useDropzone } from "react-dropzone";
|
||||||
|
import { CloudUpload } from "lucide-react";
|
||||||
|
import Image from "next/image";
|
||||||
|
import { Upload } from "tus-js-client";
|
||||||
|
import { id } from "date-fns/locale";
|
||||||
|
import { htmlToString } from "@/utils/globals";
|
||||||
|
|
||||||
|
const FormSchema = z.object({
|
||||||
|
answer: z.string({
|
||||||
|
required_error: "Required",
|
||||||
|
}),
|
||||||
|
question: z.string({
|
||||||
|
required_error: "Required",
|
||||||
|
}),
|
||||||
|
publishTo: z.string({
|
||||||
|
required_error: "Required",
|
||||||
|
}),
|
||||||
|
|
||||||
|
// publishTo: z.array(z.string()).refine((value) => value.some((item) => item), {
|
||||||
|
// message: "Required",
|
||||||
|
// }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const publishToList = [
|
||||||
|
{
|
||||||
|
id: "mabes",
|
||||||
|
name: "Nasional",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "polda",
|
||||||
|
name: "Polda",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "satker",
|
||||||
|
name: "Satker",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "internasional",
|
||||||
|
name: "Internasional",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function EditSpvFAQModal(props: {
|
||||||
|
id: string;
|
||||||
|
isDetail: boolean;
|
||||||
|
}) {
|
||||||
|
const { id, isDetail } = props;
|
||||||
|
const router = useRouter();
|
||||||
|
const { toast } = useToast();
|
||||||
|
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const form = useForm<z.infer<typeof FormSchema>>({
|
||||||
|
resolver: zodResolver(FormSchema),
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
initState();
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
const initState = async () => {
|
||||||
|
const res = await detailDataFAQ(id);
|
||||||
|
const data = res?.data?.data;
|
||||||
|
form.setValue("question", htmlToString(data.question));
|
||||||
|
form.setValue("answer", htmlToString(data.answer));
|
||||||
|
form.setValue(
|
||||||
|
"publishTo",
|
||||||
|
data.isInternational ? "international" : "wilayah"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = async (data: z.infer<typeof FormSchema>) => {
|
||||||
|
const request = {
|
||||||
|
id: Number(id),
|
||||||
|
question: data.question,
|
||||||
|
answer: data.answer,
|
||||||
|
isInternational: data.publishTo === "wilayah" ? false : true,
|
||||||
|
isActive: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await postDataFAQ(request);
|
||||||
|
close();
|
||||||
|
if (response?.error) {
|
||||||
|
toast({ title: stringify(response.message), variant: "destructive" });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
toast({
|
||||||
|
title: "Succes",
|
||||||
|
description: "FAQ berhasil diubah",
|
||||||
|
});
|
||||||
|
router.push("/supervisor/faq?dataChange=true");
|
||||||
|
setIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<a className="hover:underline cursor-pointer">
|
||||||
|
{isDetail ? "Detail" : "Edit"}
|
||||||
|
</a>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent size="md">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>{isDetail ? "Detail" : "Edit"} FAQ</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<Form {...form}>
|
||||||
|
<form
|
||||||
|
onSubmit={form.handleSubmit(onSubmit)}
|
||||||
|
className="space-y-3 bg-white rounded-sm"
|
||||||
|
>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="publishTo"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="space-y-3">
|
||||||
|
<FormLabel>Wilayah Publish</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<RadioGroup
|
||||||
|
onValueChange={field.onChange}
|
||||||
|
value={field.value}
|
||||||
|
className="flex flex-row space-x-1"
|
||||||
|
>
|
||||||
|
<FormItem className="flex items-center space-x-3 space-y-0">
|
||||||
|
<FormControl>
|
||||||
|
<RadioGroupItem value="wilayah" />
|
||||||
|
</FormControl>
|
||||||
|
<FormLabel className="font-normal">Wilayah</FormLabel>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem className="flex items-center space-x-3 space-y-0">
|
||||||
|
<FormControl>
|
||||||
|
<RadioGroupItem value="international" />
|
||||||
|
</FormControl>
|
||||||
|
<FormLabel className="font-normal">
|
||||||
|
Internasional
|
||||||
|
</FormLabel>
|
||||||
|
</FormItem>
|
||||||
|
</RadioGroup>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="question"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Pertanyaan</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Textarea
|
||||||
|
readOnly={isDetail}
|
||||||
|
placeholder="Masukkan pertanyaan"
|
||||||
|
value={field.value}
|
||||||
|
onChange={field.onChange}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="answer"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Jawaban</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Textarea
|
||||||
|
readOnly={isDetail}
|
||||||
|
placeholder="Masukkan jawaban"
|
||||||
|
value={field.value}
|
||||||
|
onChange={field.onChange}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{!isDetail && (
|
||||||
|
<DialogFooter>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
color="primary"
|
||||||
|
size="md"
|
||||||
|
className="text-xs"
|
||||||
|
>
|
||||||
|
Edit FAQ
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
)}
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -24,37 +24,32 @@ import {
|
||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
|
||||||
import {
|
import { useSearchParams } from "next/navigation";
|
||||||
ChevronLeft,
|
|
||||||
ChevronRight,
|
|
||||||
Eye,
|
|
||||||
MoreVertical,
|
|
||||||
Search,
|
|
||||||
SquarePen,
|
|
||||||
Trash2,
|
|
||||||
TrendingDown,
|
|
||||||
TrendingUp,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from "@/components/ui/dropdown-menu";
|
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { InputGroup, InputGroupText } from "@/components/ui/input-group";
|
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
import { useRouter, useSearchParams } from "next/navigation";
|
|
||||||
import TablePagination from "@/components/table/table-pagination";
|
import TablePagination from "@/components/table/table-pagination";
|
||||||
import { getFaqList } from "@/service/master/faq";
|
|
||||||
import columns from "./column";
|
import columns from "./column";
|
||||||
|
|
||||||
const FaqTable = () => {
|
import { listEnableCategory } from "@/service/content/content";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { close, loading } from "@/config/swal";
|
||||||
|
import { Link, useRouter } from "@/i18n/routing";
|
||||||
|
import { NewCampaignIcon } from "@/components/icon";
|
||||||
|
import { getCategories, getListFAQ } from "@/service/settings/settings";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import CreateSpvFAQModal from "./create";
|
||||||
|
|
||||||
|
const SpvFAQTable = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
|
const dataChange = searchParams?.get("dataChange");
|
||||||
|
const [openModal, setOpenModal] = React.useState(false);
|
||||||
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
||||||
const [totalData, setTotalData] = React.useState<number>(1);
|
const [totalData, setTotalData] = React.useState<number>(1);
|
||||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||||
|
|
@ -68,10 +63,9 @@ const FaqTable = () => {
|
||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [page, setPage] = React.useState(1);
|
const [page, setPage] = React.useState(1);
|
||||||
const [totalPage, setTotalPage] = React.useState(1);
|
const [totalPage, setTotalPage] = React.useState(1);
|
||||||
const [limit, setLimit] = React.useState(10);
|
|
||||||
|
|
||||||
const table = useReactTable({
|
const table = useReactTable({
|
||||||
data: dataTable,
|
data: dataTable,
|
||||||
columns,
|
columns,
|
||||||
|
|
@ -94,63 +88,50 @@ const FaqTable = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const pageFromUrl = searchParams?.get('page');
|
if (dataChange) {
|
||||||
|
router.push("/admin/settings/faq");
|
||||||
|
}
|
||||||
|
fetchData();
|
||||||
|
}, [dataChange]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const pageFromUrl = searchParams?.get("page");
|
||||||
if (pageFromUrl) {
|
if (pageFromUrl) {
|
||||||
setPage(Number(pageFromUrl));
|
setPage(Number(pageFromUrl));
|
||||||
}
|
}
|
||||||
}, [searchParams]);
|
}, [searchParams]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
}, [page, limit]);
|
}, [page]);
|
||||||
|
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
try {
|
try {
|
||||||
const res = await getFaqList();
|
loading();
|
||||||
const contentData = res?.data?.data;
|
const response = await getListFAQ();
|
||||||
contentData.forEach((item: any, index: number) => {
|
const data = response?.data?.data;
|
||||||
item.no = (page - 1) * limit + index + 1;
|
console.log("respone", response);
|
||||||
|
data.forEach((item: any, index: number) => {
|
||||||
|
item.no = (page - 1) * 10 + index + 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("contentData : ", contentData);
|
setDataTable(data);
|
||||||
|
setTotalData(data?.length);
|
||||||
setDataTable(contentData);
|
setTotalPage(1);
|
||||||
setTotalData(contentData?.totalElements || contentData?.length);
|
close();
|
||||||
setTotalPage(contentData?.totalPages || 1);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching tasks:", error);
|
console.error("Error fetching tasks:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full overflow-x-auto">
|
<div className="w-full overflow-x-auto bg-white p-4 rounded-sm space-y-3">
|
||||||
<div className="flex justify-between items-center px-6">
|
<div className="flex justify-between mb-10 items-center">
|
||||||
<div>
|
<p className="text-xl font-medium text-default-900">FAQ</p>
|
||||||
<InputGroup merged>
|
<CreateSpvFAQModal />
|
||||||
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
|
|
||||||
<Search className=" h-4 w-4 dark:text-white" />
|
|
||||||
</InputGroupText>
|
|
||||||
<Input
|
|
||||||
type="text"
|
|
||||||
placeholder="Search Judul..."
|
|
||||||
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
|
|
||||||
/>
|
|
||||||
</InputGroup>
|
|
||||||
</div>
|
|
||||||
<div className="flex-none">
|
|
||||||
<Input
|
|
||||||
placeholder="Filter Status..."
|
|
||||||
value={
|
|
||||||
(table.getColumn("status")?.getFilterValue() as string) ?? ""
|
|
||||||
}
|
|
||||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
|
||||||
table.getColumn("status")?.setFilterValue(event.target.value)
|
|
||||||
}
|
|
||||||
className="max-w-sm "
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<Table className="overflow-hidden mt-3">
|
|
||||||
|
<Table className="overflow-hidden">
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
{table.getHeaderGroups().map((headerGroup) => (
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
<TableRow key={headerGroup.id} className="bg-default-200">
|
<TableRow key={headerGroup.id} className="bg-default-200">
|
||||||
|
|
@ -191,9 +172,13 @@ const FaqTable = () => {
|
||||||
)}
|
)}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
<TablePagination table={table} totalData={totalData} totalPage={totalPage} visiblePageCount={5} />
|
{/* <TablePagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/> */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FaqTable;
|
export default SpvFAQTable;
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,11 @@
|
||||||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import SpvFAQTable from "./components/table";
|
||||||
import FaqTable from "./components/table";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Plus } from "lucide-react";
|
|
||||||
|
|
||||||
const FaqPage = async () => {
|
const FaqPage = async () => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SiteBreadcrumb />
|
<SiteBreadcrumb />
|
||||||
<div className="space-y-4">
|
<SpvFAQTable />
|
||||||
<Card>
|
|
||||||
<CardHeader className="border-b border-solid border-default-200 mb-6">
|
|
||||||
<CardTitle>
|
|
||||||
<div className="flex items-center">
|
|
||||||
<div className="flex-1 text-xl font-medium text-default-900">
|
|
||||||
FAQ Data
|
|
||||||
</div>
|
|
||||||
<div className="flex-none">
|
|
||||||
<Button
|
|
||||||
fullWidth
|
|
||||||
size="md"
|
|
||||||
>
|
|
||||||
<Plus className="w-6 h-6 me-1.5"/>
|
|
||||||
New FAQ
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="p-0">
|
|
||||||
<FaqTable />
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,7 @@
|
||||||
|
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import {
|
import { ColumnDef } from "@tanstack/react-table";
|
||||||
ColumnDef,
|
|
||||||
} from "@tanstack/react-table";
|
|
||||||
|
|
||||||
import {
|
import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react";
|
||||||
Eye,
|
|
||||||
MoreVertical,
|
|
||||||
SquarePen,
|
|
||||||
Trash2,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
|
|
@ -19,6 +11,7 @@ import {
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { formatDateToIndonesian } from "@/utils/globals";
|
||||||
|
|
||||||
const columns: ColumnDef<any>[] = [
|
const columns: ColumnDef<any>[] = [
|
||||||
{
|
{
|
||||||
|
|
@ -34,19 +27,23 @@ const columns: ColumnDef<any>[] = [
|
||||||
{
|
{
|
||||||
accessorKey: "title",
|
accessorKey: "title",
|
||||||
header: "Title",
|
header: "Title",
|
||||||
cell: ({ row }) => <span>{row.getValue("title")}</span>,
|
cell: ({ row }) => (
|
||||||
|
<span className="normal-case">{row.getValue("title")}</span>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "commentFromUserName",
|
accessorKey: "commentFromUserName",
|
||||||
header: "Sender",
|
header: "Sender",
|
||||||
cell: ({ row }) => <span>{row.getValue("commentFromUserName")}</span>,
|
cell: ({ row }) => (
|
||||||
|
<span className="normal-case">{row.getValue("commentFromUserName")}</span>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "type",
|
accessorKey: "type",
|
||||||
header: "Channel",
|
header: "Channel",
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const type = row.getValue("type") as { name: string };
|
const type = row.getValue("type") as { name: string };
|
||||||
return <span>{type?.name}</span>;
|
return <span className="normal-case">{type?.name}</span>;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -54,14 +51,16 @@ const columns: ColumnDef<any>[] = [
|
||||||
header: "Operator",
|
header: "Operator",
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const createdBy = row.getValue("createdBy") as { fullname: string };
|
const createdBy = row.getValue("createdBy") as { fullname: string };
|
||||||
return <span>{createdBy?.fullname}</span>;
|
return <span className="normal-case">{createdBy?.fullname}</span>;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "createdAt",
|
accessorKey: "createdAt",
|
||||||
header: "Tanggal Unggah ",
|
header: "Tanggal Unggah ",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<span className="whitespace-nowrap">{row.getValue("createdAt")}</span>
|
<span className="whitespace-nowrap">
|
||||||
|
{formatDateToIndonesian(row.getValue("createdAt"))}
|
||||||
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -72,18 +71,18 @@ const columns: ColumnDef<any>[] = [
|
||||||
open: "bg-primary/20 text-primary",
|
open: "bg-primary/20 text-primary",
|
||||||
close: "bg-success/20 text-success",
|
close: "bg-success/20 text-success",
|
||||||
};
|
};
|
||||||
const status = row.getValue("status") as { id: number, name: string };;
|
const status = row.getValue("status") as { id: number; name: string };
|
||||||
const statusName = status?.name?.toLocaleLowerCase();
|
const statusName = status?.name?.toLocaleLowerCase();
|
||||||
console.log(statusName);
|
console.log(statusName);
|
||||||
const statusStyles = statusColors[statusName] || "default";
|
const statusStyles = statusColors[statusName] || "default";
|
||||||
if (statusName) {
|
if (statusName) {
|
||||||
return (
|
return (
|
||||||
<Badge
|
<Badge className={cn("rounded-full px-5", statusStyles)}>
|
||||||
className={cn("rounded-full px-5",statusStyles)}
|
{statusName}{" "}
|
||||||
>{statusName} </Badge>
|
</Badge>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "actions",
|
id: "actions",
|
||||||
|
|
@ -122,4 +121,4 @@ const columns: ColumnDef<any>[] = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default columns;
|
export default columns;
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@ import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
|
DropdownMenuRadioGroup,
|
||||||
|
DropdownMenuRadioItem,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
|
|
@ -62,16 +64,19 @@ const TicketingTable = () => {
|
||||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
const [search, setSearch] = React.useState("");
|
||||||
|
|
||||||
const [columnVisibility, setColumnVisibility] =
|
const [columnVisibility, setColumnVisibility] =
|
||||||
React.useState<VisibilityState>({});
|
React.useState<VisibilityState>({});
|
||||||
|
const [showData, setShowData] = React.useState("10");
|
||||||
|
|
||||||
const [rowSelection, setRowSelection] = React.useState({});
|
const [rowSelection, setRowSelection] = React.useState({});
|
||||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
pageSize: 10,
|
pageSize: Number(showData),
|
||||||
});
|
});
|
||||||
const [page, setPage] = React.useState(1);
|
const [page, setPage] = React.useState(1);
|
||||||
const [totalPage, setTotalPage] = React.useState(1);
|
const [totalPage, setTotalPage] = React.useState(1);
|
||||||
const [limit, setLimit] = React.useState(10);
|
|
||||||
|
|
||||||
const table = useReactTable({
|
const table = useReactTable({
|
||||||
data: dataTable,
|
data: dataTable,
|
||||||
|
|
@ -94,24 +99,40 @@ const TicketingTable = () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let typingTimer: any;
|
||||||
|
const doneTypingInterval = 1500;
|
||||||
|
|
||||||
|
const handleKeyUp = () => {
|
||||||
|
clearTimeout(typingTimer);
|
||||||
|
typingTimer = setTimeout(doneTyping, doneTypingInterval);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleKeyDown = () => {
|
||||||
|
clearTimeout(typingTimer);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function doneTyping() {
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const pageFromUrl = searchParams?.get('page');
|
const pageFromUrl = searchParams?.get("page");
|
||||||
if (pageFromUrl) {
|
if (pageFromUrl) {
|
||||||
setPage(Number(pageFromUrl));
|
setPage(Number(pageFromUrl));
|
||||||
}
|
}
|
||||||
}, [searchParams]);
|
}, [searchParams]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
}, [page, limit]);
|
}, [page]);
|
||||||
|
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
try {
|
try {
|
||||||
const res = await ticketingPagination('', limit, page-1);
|
const res = await ticketingPagination(search, Number(showData), page - 1);
|
||||||
const data = res?.data?.data;
|
const data = res?.data?.data;
|
||||||
const contentData = data?.content;
|
const contentData = data?.content;
|
||||||
contentData.forEach((item: any, index: number) => {
|
contentData.forEach((item: any, index: number) => {
|
||||||
item.no = (page - 1) * limit + index + 1;
|
item.no = (page - 1) * Number(showData) + index + 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("contentData : ", contentData);
|
console.log("contentData : ", contentData);
|
||||||
|
|
@ -125,34 +146,46 @@ const TicketingTable = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full overflow-x-auto">
|
<>
|
||||||
<div className="flex justify-between items-center px-5">
|
<div className="flex justify-between py-3">
|
||||||
<div>
|
<Input
|
||||||
<InputGroup merged>
|
type="text"
|
||||||
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
|
placeholder="Search"
|
||||||
<Search className=" h-4 w-4 dark:text-white" />
|
onKeyUp={handleKeyUp}
|
||||||
</InputGroupText>
|
onKeyDown={handleKeyDown}
|
||||||
<Input
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
type="text"
|
className="max-w-[300px]"
|
||||||
placeholder="Search Judul..."
|
/>
|
||||||
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
|
<div className="flex flex-row gap-2">
|
||||||
/>
|
<DropdownMenu>
|
||||||
</InputGroup>
|
<DropdownMenuTrigger asChild>
|
||||||
</div>
|
<Button size="md" variant="outline">
|
||||||
<div className="flex-none">
|
1 - {showData} Data
|
||||||
<Input
|
</Button>
|
||||||
placeholder="Filter Status..."
|
</DropdownMenuTrigger>
|
||||||
value={
|
<DropdownMenuContent className="w-56 text-sm">
|
||||||
(table.getColumn("status")?.getFilterValue() as string) ?? ""
|
<DropdownMenuRadioGroup
|
||||||
}
|
value={showData}
|
||||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
onValueChange={setShowData}
|
||||||
table.getColumn("status")?.setFilterValue(event.target.value)
|
>
|
||||||
}
|
<DropdownMenuRadioItem value="10">
|
||||||
className="max-w-sm "
|
1 - 10 Data
|
||||||
/>
|
</DropdownMenuRadioItem>
|
||||||
|
<DropdownMenuRadioItem value="20">
|
||||||
|
1 - 20 Data
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
<DropdownMenuRadioItem value="25">
|
||||||
|
1 - 25 Data
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
<DropdownMenuRadioItem value="50">
|
||||||
|
1 - 50 Data
|
||||||
|
</DropdownMenuRadioItem>
|
||||||
|
</DropdownMenuRadioGroup>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Table className="overflow-hidden mt-3">
|
<Table className="overflow-hidden">
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
{table.getHeaderGroups().map((headerGroup) => (
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
<TableRow key={headerGroup.id} className="bg-default-200">
|
<TableRow key={headerGroup.id} className="bg-default-200">
|
||||||
|
|
@ -193,8 +226,12 @@ const TicketingTable = () => {
|
||||||
)}
|
)}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
<TablePagination table={table} totalData={totalData} totalPage={totalPage} />
|
<TablePagination
|
||||||
</div>
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,21 @@
|
||||||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { UploadIcon } from "lucide-react";
|
|
||||||
import TicketingTable from "./components/table";
|
import TicketingTable from "./components/table";
|
||||||
|
|
||||||
const TicketingPage = async () => {
|
const TicketingPage = async () => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SiteBreadcrumb />
|
<SiteBreadcrumb />
|
||||||
<div className="space-y-4">
|
|
||||||
<Card>
|
<section
|
||||||
<CardHeader className="border-b border-solid border-default-200 mb-6">
|
id="table"
|
||||||
<CardTitle>
|
className="flex flex-col gap-2 bg-white rounded-lg p-3 mt-5"
|
||||||
<div className="flex items-center">
|
>
|
||||||
<div className="flex-1 text-xl font-medium text-default-900">
|
<div className="flex justify-between py-3">
|
||||||
Ticket Data
|
<p className="text-lg">Semua Ticket</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-none">
|
|
||||||
{/* <Button
|
<TicketingTable />
|
||||||
fullWidth
|
</section>
|
||||||
size="md"
|
|
||||||
>
|
|
||||||
<Plus className="w-6 h-6 me-1.5"/>
|
|
||||||
New Ticket
|
|
||||||
</Button> */}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="p-0">
|
|
||||||
<TicketingTable />
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -24,20 +24,6 @@ import {
|
||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "@/components/ui/table";
|
} from "@/components/ui/table";
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
|
||||||
import {
|
|
||||||
ChevronLeft,
|
|
||||||
ChevronRight,
|
|
||||||
Eye,
|
|
||||||
MoreVertical,
|
|
||||||
PlusIcon,
|
|
||||||
Search,
|
|
||||||
SquarePen,
|
|
||||||
Trash2,
|
|
||||||
TrendingDown,
|
|
||||||
TrendingUp,
|
|
||||||
UserIcon,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { cn, getCookiesDecrypt } from "@/lib/utils";
|
import { cn, getCookiesDecrypt } from "@/lib/utils";
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
|
|
@ -75,7 +61,6 @@ const UserInternalTable = () => {
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const dataChange = searchParams?.get("dataChange");
|
const dataChange = searchParams?.get("dataChange");
|
||||||
const [showData, setShowData] = React.useState("10");
|
const [showData, setShowData] = React.useState("10");
|
||||||
const [categories, setCategories] = React.useState<any>();
|
|
||||||
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
||||||
const [totalData, setTotalData] = React.useState<number>(1);
|
const [totalData, setTotalData] = React.useState<number>(1);
|
||||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue