| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- import { useState } from 'react'
- import { type Table } from '@tanstack/react-table'
- import { Trash2, CircleArrowUp, ArrowUpDown, Download } from 'lucide-react'
- import { toast } from 'sonner'
- import { sleep } from '@/utils/sleep'
- import { Button } from '@/components/ui/button'
- import {
- DropdownMenu,
- DropdownMenuContent,
- DropdownMenuItem,
- DropdownMenuTrigger,
- } from '@/components/ui/dropdown-menu'
- import {
- Tooltip,
- TooltipContent,
- TooltipTrigger,
- } from '@/components/ui/tooltip'
- import { DataTableBulkActions as BulkActionsToolbar } from '@/components/data-table'
- import { priorities, statuses } from '../data/data'
- import { type Task } from '../data/schema'
- import { TasksMultiDeleteDialog } from './tasks-multi-delete-dialog'
- type DataTableBulkActionsProps<TData> = {
- table: Table<TData>
- }
- export function DataTableBulkActions<TData>({
- table,
- }: DataTableBulkActionsProps<TData>) {
- const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)
- const selectedRows = table.getFilteredSelectedRowModel().rows
- const handleBulkStatusChange = (status: string) => {
- const selectedTasks = selectedRows.map((row) => row.original as Task)
- toast.promise(sleep(2000), {
- loading: 'Updating status...',
- success: () => {
- table.resetRowSelection()
- return `Status updated to "${status}" for ${selectedTasks.length} task${selectedTasks.length > 1 ? 's' : ''}.`
- },
- error: 'Error',
- })
- table.resetRowSelection()
- }
- const handleBulkPriorityChange = (priority: string) => {
- const selectedTasks = selectedRows.map((row) => row.original as Task)
- toast.promise(sleep(2000), {
- loading: 'Updating priority...',
- success: () => {
- table.resetRowSelection()
- return `Priority updated to "${priority}" for ${selectedTasks.length} task${selectedTasks.length > 1 ? 's' : ''}.`
- },
- error: 'Error',
- })
- table.resetRowSelection()
- }
- const handleBulkExport = () => {
- const selectedTasks = selectedRows.map((row) => row.original as Task)
- toast.promise(sleep(2000), {
- loading: 'Exporting tasks...',
- success: () => {
- table.resetRowSelection()
- return `Exported ${selectedTasks.length} task${selectedTasks.length > 1 ? 's' : ''} to CSV.`
- },
- error: 'Error',
- })
- table.resetRowSelection()
- }
- return (
- <>
- <BulkActionsToolbar table={table} entityName='task'>
- <DropdownMenu>
- <Tooltip>
- <TooltipTrigger asChild>
- <DropdownMenuTrigger asChild>
- <Button
- variant='outline'
- size='icon'
- className='size-8'
- aria-label='Update status'
- title='Update status'
- >
- <CircleArrowUp />
- <span className='sr-only'>Update status</span>
- </Button>
- </DropdownMenuTrigger>
- </TooltipTrigger>
- <TooltipContent>
- <p>Update status</p>
- </TooltipContent>
- </Tooltip>
- <DropdownMenuContent sideOffset={14}>
- {statuses.map((status) => (
- <DropdownMenuItem
- key={status.value}
- defaultValue={status.value}
- onClick={() => handleBulkStatusChange(status.value)}
- >
- {status.icon && (
- <status.icon className='text-muted-foreground size-4' />
- )}
- {status.label}
- </DropdownMenuItem>
- ))}
- </DropdownMenuContent>
- </DropdownMenu>
- <DropdownMenu>
- <Tooltip>
- <TooltipTrigger asChild>
- <DropdownMenuTrigger asChild>
- <Button
- variant='outline'
- size='icon'
- className='size-8'
- aria-label='Update priority'
- title='Update priority'
- >
- <ArrowUpDown />
- <span className='sr-only'>Update priority</span>
- </Button>
- </DropdownMenuTrigger>
- </TooltipTrigger>
- <TooltipContent>
- <p>Update priority</p>
- </TooltipContent>
- </Tooltip>
- <DropdownMenuContent sideOffset={14}>
- {priorities.map((priority) => (
- <DropdownMenuItem
- key={priority.value}
- defaultValue={priority.value}
- onClick={() => handleBulkPriorityChange(priority.value)}
- >
- {priority.icon && (
- <priority.icon className='text-muted-foreground size-4' />
- )}
- {priority.label}
- </DropdownMenuItem>
- ))}
- </DropdownMenuContent>
- </DropdownMenu>
- <Tooltip>
- <TooltipTrigger asChild>
- <Button
- variant='outline'
- size='icon'
- onClick={() => handleBulkExport()}
- className='size-8'
- aria-label='Export tasks'
- title='Export tasks'
- >
- <Download />
- <span className='sr-only'>Export tasks</span>
- </Button>
- </TooltipTrigger>
- <TooltipContent>
- <p>Export tasks</p>
- </TooltipContent>
- </Tooltip>
- <Tooltip>
- <TooltipTrigger asChild>
- <Button
- variant='destructive'
- size='icon'
- onClick={() => setShowDeleteConfirm(true)}
- className='size-8'
- aria-label='Delete selected tasks'
- title='Delete selected tasks'
- >
- <Trash2 />
- <span className='sr-only'>Delete selected tasks</span>
- </Button>
- </TooltipTrigger>
- <TooltipContent>
- <p>Delete selected tasks</p>
- </TooltipContent>
- </Tooltip>
- </BulkActionsToolbar>
- <TasksMultiDeleteDialog
- open={showDeleteConfirm}
- onOpenChange={setShowDeleteConfirm}
- table={table}
- />
- </>
- )
- }
|