"use client" import { useState, useEffect } from 'react' import { useRouter } from 'next/navigation' import { Plus, MoreHorizontal, ArrowUpDown, ChevronDown } from 'lucide-react' import { ColumnDef, ColumnFiltersState, flexRender, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, SortingState, useReactTable, VisibilityState, } from "@tanstack/react-table" import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Badge } from '@/components/ui/badge' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' import { useToast } from '@/hooks/use-toast' import type { Artist } from '@/types/database' export default function ArtistsPage() { const router = useRouter() const { toast } = useToast() const [artists, setArtists] = useState([]) const [loading, setLoading] = useState(true) const [sorting, setSorting] = useState([]) const [columnFilters, setColumnFilters] = useState([]) const [columnVisibility, setColumnVisibility] = useState({}) const [rowSelection, setRowSelection] = useState({}) // Define columns for the data table const columns: ColumnDef[] = [ { accessorKey: "name", header: ({ column }) => { return ( ) }, cell: ({ row }) => (
{row.getValue("name")}
), }, { accessorKey: "specialties", header: "Specialties", cell: ({ row }) => { const specialties = row.getValue("specialties") as string const specialtiesArray = specialties ? JSON.parse(specialties) : [] return (
{specialtiesArray.slice(0, 2).map((specialty: string) => ( {specialty} ))} {specialtiesArray.length > 2 && ( +{specialtiesArray.length - 2} )}
) }, }, { accessorKey: "hourlyRate", header: ({ column }) => { return ( ) }, cell: ({ row }) => { const rate = row.getValue("hourlyRate") as number return rate ? `$${rate}/hr` : 'Not set' }, }, { accessorKey: "isActive", header: "Status", cell: ({ row }) => { const isActive = row.getValue("isActive") as boolean return ( {isActive ? "Active" : "Inactive"} ) }, }, { accessorKey: "createdAt", header: "Created", cell: ({ row }) => { const date = new Date(row.getValue("createdAt")) return date.toLocaleDateString() }, }, { id: "actions", enableHiding: false, cell: ({ row }) => { const artist = row.original return ( Actions router.push(`/admin/artists/${artist.id}`)} > Edit artist router.push(`/admin/artists/${artist.id}/portfolio`)} > Manage portfolio handleToggleStatus(artist)} className={artist.isActive ? "text-red-600" : "text-green-600"} > {artist.isActive ? "Deactivate" : "Activate"} ) }, }, ] const table = useReactTable({ data: artists, columns, onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), getSortedRowModel: getSortedRowModel(), getFilteredRowModel: getFilteredRowModel(), onColumnVisibilityChange: setColumnVisibility, onRowSelectionChange: setRowSelection, state: { sorting, columnFilters, columnVisibility, rowSelection, }, }) const fetchArtists = async () => { try { const response = await fetch('/api/artists') if (!response.ok) throw new Error('Failed to fetch artists') const data = await response.json() setArtists(data.artists || []) } catch (error) { console.error('Error fetching artists:', error) toast({ title: 'Error', description: 'Failed to load artists', variant: 'destructive', }) } finally { setLoading(false) } } const handleToggleStatus = async (artist: Artist) => { try { const response = await fetch(`/api/artists/${artist.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ isActive: !artist.isActive, }), }) if (!response.ok) throw new Error('Failed to update artist') toast({ title: 'Success', description: `Artist ${artist.isActive ? 'deactivated' : 'activated'} successfully`, }) // Refresh the list fetchArtists() } catch (error) { console.error('Error updating artist:', error) toast({ title: 'Error', description: 'Failed to update artist status', variant: 'destructive', }) } } useEffect(() => { fetchArtists() }, []) if (loading) { return (
Loading artists...
) } return (

Artists

Manage your tattoo artists and their information

All Artists
{/* Filters and Controls */}
table.getColumn("name")?.setFilterValue(event.target.value) } className="max-w-sm" />
{table .getAllColumns() .filter((column) => column.getCanHide()) .map((column) => { return ( column.toggleVisibility(!!value) } > {column.id} ) })}
{/* Data Table */}
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => { return ( {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext() )} ) })} ))} {table.getRowModel().rows?.length ? ( table.getRowModel().rows.map((row) => ( router.push(`/admin/artists/${row.original.id}`)} > {row.getVisibleCells().map((cell) => ( {flexRender( cell.column.columnDef.cell, cell.getContext() )} ))} )) ) : ( No artists found. )}
{/* Pagination */}
{table.getFilteredSelectedRowModel().rows.length} of{" "} {table.getFilteredRowModel().rows.length} row(s) selected.
) }