123 lines
3.9 KiB
TypeScript
123 lines
3.9 KiB
TypeScript
import type { ColumnDef } from '@tanstack/react-table';
|
|
import { format } from 'date-fns';
|
|
import { Pencil, Trash2 } from 'lucide-react';
|
|
import { RowActions } from '@/components/row-actions';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import type { Feedback, FeedbackStatusValue } from '@/types/feedback';
|
|
import { FeedbackStatusLabels, FeedbackTypeLabels } from '@/types/feedback';
|
|
|
|
export type { Feedback } from '@/types/feedback';
|
|
|
|
type CreateColumnsParams = {
|
|
handleEdit: (feedback: Feedback) => void;
|
|
handleDeleteClick: (feedback: Feedback) => void;
|
|
};
|
|
|
|
function stripHtml(html: string): string {
|
|
return html
|
|
.replace(/<[^>]+>/g, ' ')
|
|
.replace(/\s+/g, ' ')
|
|
.trim();
|
|
}
|
|
|
|
function statusBadgeVariant(
|
|
status: FeedbackStatusValue,
|
|
): 'outline' | 'secondary' | 'default' {
|
|
if (status === 'resolved') {
|
|
return 'default';
|
|
}
|
|
|
|
if (status === 'in_review') {
|
|
return 'secondary';
|
|
}
|
|
|
|
return 'outline';
|
|
}
|
|
|
|
export function createFeedbackColumns(
|
|
params: CreateColumnsParams,
|
|
): ColumnDef<Feedback>[] {
|
|
const { handleEdit, handleDeleteClick } = params;
|
|
|
|
return [
|
|
{
|
|
accessorKey: 'subject',
|
|
header: () => <span>Subjek</span>,
|
|
cell: ({ row }) => {
|
|
const feedback = row.original;
|
|
|
|
return (
|
|
<div>
|
|
<p className="font-medium">{feedback.subject}</p>
|
|
<p className="line-clamp-1 text-xs text-muted-foreground">
|
|
{stripHtml(feedback.message)}
|
|
</p>
|
|
</div>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
accessorKey: 'type',
|
|
header: () => <span className="block text-center">Jenis</span>,
|
|
meta: {
|
|
className: 'w-[110px] text-center',
|
|
headerClassName: 'w-[110px] text-center',
|
|
},
|
|
cell: ({ row }) => (
|
|
<div className="flex justify-center">
|
|
<Badge variant="outline">
|
|
{FeedbackTypeLabels[row.original.type]}
|
|
</Badge>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
accessorKey: 'status',
|
|
header: () => <span className="block text-center">Status</span>,
|
|
meta: {
|
|
className: 'w-[130px] text-center',
|
|
headerClassName: 'w-[130px] text-center',
|
|
},
|
|
cell: ({ row }) => (
|
|
<div className="flex justify-center">
|
|
<Badge variant={statusBadgeVariant(row.original.status)}>
|
|
{FeedbackStatusLabels[row.original.status]}
|
|
</Badge>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
accessorKey: 'created_at',
|
|
header: () => <span>Dikirim</span>,
|
|
cell: ({ row }) =>
|
|
format(new Date(row.original.created_at), 'd MMM yyyy, HH:mm'),
|
|
},
|
|
{
|
|
id: 'actions',
|
|
header: () => <span className="block text-center">Aksi</span>,
|
|
meta: {
|
|
className: 'w-[100px] text-center',
|
|
headerClassName: 'w-[100px] text-center',
|
|
},
|
|
cell: ({ row }) => (
|
|
<RowActions
|
|
actions={[
|
|
{
|
|
label: 'Edit',
|
|
icon: <Pencil className="h-4 w-4" />,
|
|
onClick: () => handleEdit(row.original),
|
|
},
|
|
{
|
|
label: 'Hapus',
|
|
icon: (
|
|
<Trash2 className="h-4 w-4 text-destructive" />
|
|
),
|
|
onClick: () => handleDeleteClick(row.original),
|
|
},
|
|
]}
|
|
/>
|
|
),
|
|
},
|
|
];
|
|
}
|