- Implemented TemplateCheckpointEditDialog for creating and editing inspection checkpoints. - Added VendorActions component for managing vendor actions including edit, activate/deactivate, and delete. - Created VendorContext for managing vendor state across components. - Developed VendorGeneralInfo component to display detailed vendor information. - Introduced AedSymbol and Money components for consistent currency representation. - Added PromptDialog for user input prompts throughout the application. - Implemented RelationLink component for unified related-data display in CRUD tables. - Created InspectionTemplatesClient for API interactions related to inspection templates.
102 lines
3.5 KiB
TypeScript
102 lines
3.5 KiB
TypeScript
"use client"
|
|
|
|
import type { ColumnDef, Row } from "@tanstack/react-table"
|
|
import type { ComponentType } from "react"
|
|
import { MoreHorizontal, Pencil, Trash2 } from "lucide-react"
|
|
import { Button } from "@/shared/components/ui/button"
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuTrigger,
|
|
} from "@/shared/components/ui/dropdown-menu"
|
|
|
|
export type ActionsColumnExtraItem<TData> = {
|
|
label: string
|
|
icon?: ComponentType<{ className?: string }>
|
|
onClick: (row: TData) => void | Promise<unknown>
|
|
variant?: "default" | "destructive"
|
|
/** Hide the item entirely when false. Useful for permission gates. */
|
|
hidden?: boolean
|
|
}
|
|
|
|
export type ActionsColumnOptions<TData> = {
|
|
onEdit?: (row: TData) => void
|
|
onDelete?: (row: TData) => Promise<unknown>
|
|
/** Extra menu items rendered between Edit and Delete. */
|
|
extraItems?: (row: TData) => ActionsColumnExtraItem<TData>[]
|
|
}
|
|
|
|
export function createActionsColumn<TData extends { id: string | number }>(
|
|
options: ActionsColumnOptions<TData>,
|
|
): ColumnDef<TData, unknown> {
|
|
return {
|
|
id: "actions",
|
|
header: () => <span className="sr-only">Actions</span>,
|
|
cell: ({ row }) => <ActionsCell row={row} options={options} />,
|
|
enableSorting: false,
|
|
enableHiding: false,
|
|
}
|
|
}
|
|
|
|
function ActionsCell<TData extends { id: string | number }>({
|
|
row,
|
|
options,
|
|
}: {
|
|
row: Row<TData>
|
|
options: ActionsColumnOptions<TData>
|
|
}) {
|
|
return (
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<Button variant="ghost" size="icon-sm">
|
|
<MoreHorizontal className="size-4" />
|
|
<span className="sr-only">Open menu</span>
|
|
</Button>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent align="end">
|
|
{options.onEdit && (
|
|
<DropdownMenuItem onClick={(e) => {
|
|
e.stopPropagation()
|
|
options.onEdit!(row.original)
|
|
|
|
}}>
|
|
<Pencil className="size-3.5 text-muted-foreground" />
|
|
Edit
|
|
</DropdownMenuItem>
|
|
)}
|
|
{options.extraItems?.(row.original)
|
|
.filter((item) => !item.hidden)
|
|
.map((item) => {
|
|
const Icon = item.icon
|
|
return (
|
|
<DropdownMenuItem
|
|
key={item.label}
|
|
variant={item.variant}
|
|
onClick={(e) => {
|
|
e.stopPropagation()
|
|
void item.onClick(row.original)
|
|
}}
|
|
>
|
|
{Icon ? <Icon className="size-3.5 text-muted-foreground" /> : null}
|
|
{item.label}
|
|
</DropdownMenuItem>
|
|
)
|
|
})}
|
|
{options.onDelete && (
|
|
<DropdownMenuItem
|
|
variant="destructive"
|
|
onClick={(e) => {
|
|
e.stopPropagation()
|
|
options.onDelete!(row.original)
|
|
}}
|
|
>
|
|
<Trash2 className="size-3.5" />
|
|
Delete
|
|
</DropdownMenuItem>
|
|
)}
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
)
|
|
}
|