How to pass function main component to column array in Tank Stack Table 8 `@tanstack/react-table`

107 Views Asked by At

How to pass a function main component to columns array of object in Tank Stack Table @tanstack/react-table I have a trpc mutation funtion deleteUser in my component UsersListTable, I want to pass the deleteUser funtion to the columns array.

**Is there any option or method to pass the funtion?? **

My code

import React, { useState } from "react";
import Image from "next/image";
import {
  ColumnDef,
  ColumnFiltersState,
  SortingState,
  VisibilityState,
  flexRender,
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  useReactTable,
} from "@tanstack/react-table";


type FilterType = "ALL" | "RESTRICTED" | "BANNED" | "ACTIVE" | "ADMIN" | "USER";
interface UsersType {
  id: string;
  avatar: string;
  name: string;
  email: string;
  isEmailVerify: boolean;
  stripeCurrentPeriodEnd?: string | null;
  subscriptionStatus?: string | null;
  role: UserRole;
  status: UserStatus;
  createdAt: Date | string;
  _count: {
    File: number;
    Message: number;
  };
}


//////////////////////////////////////////////////////////////////////////
// I want to receive the `deleteUser` trpc mutatio function in the colums--↓↓↓↓↓↓
export const columns: ColumnDef<UsersType>[] = [
  {
    id: "select",
    header: ({ table }) => (
      <Checkbox
        checked={
          table.getIsAllPageRowsSelected() ||
          (table.getIsSomePageRowsSelected() && "indeterminate")
        }
        onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
        aria-label="Select all"
      />
    ),
    cell: ({ row }) => (
      <Checkbox
        checked={row.getIsSelected()}
        onCheckedChange={(value) => row.toggleSelected(!!value)}
        aria-label="Select row"
      />
    ),
    enableSorting: false,
    enableHiding: false,
  },
  // User name, email and avatar
  {
    accessorKey: "name",
    header: "Users",
    cell: ({ row }) => {
      return (
        <div className="flex items-center gap-2">
          <Image
            src={"/uploads/avatars/" + row.original.avatar}
            alt="Profile Image"
            width={48}
            height={48}
            className="h-12 w-12 rounded-full object-cover"
          />
          <div className="grid gap-0.5">
            <h5 className="font-semibold">{row.getValue("name")}</h5>
            <p className="text-sm text-muted-foreground">
              {row.original.email}
            </p>
          </div>
        </div>
      );
    },
  },
  // TODO: User role
  {
    accessorKey: "role",
    header: "Role",
    cell: ({ row }) => (
      <div>
        <span
          className={cn(
            "rounded-md px-2 py-1 text-xs font-semibold",
            row.getValue("role") === "ADMIN"
              ? "bg-sky-600/25 text-sky-600"
              : row.getValue("role") === "USER"
                ? "bg-lime-600/25 text-lime-600"
                : "bg-slate-200 text-slate-600",
          )}
        >
          {row.getValue("role")}
        </span>
      </div>
    ),
  }, // TODO: User role
  {
    accessorKey: "status",
    header: "Status",
    cell: ({ row }) => (
      <div>
        <span
          className={cn(
            "rounded-md px-2 py-1 text-xs font-semibold",
            row.getValue("status") === "ACTIVE"
              ? "bg-green-200 text-green-600"
              : row.getValue("status") === "RESTRICTED"
                ? "bg-amber-200 text-amber-600"
                : row.getValue("status") === "BANNED"
                  ? "bg-red-200 text-red-600"
                  : "bg-slate-200 text-slate-600",
          )}
        >
          {row.getValue("status")}
        </span>
      </div>
    ),
  },
  {
    accessorKey: "_count",
    header: "Files",
    cell: ({ row }) => (
      <div className="font-bold capitalize text-muted-foreground">
        {(row.getValue("_count") as { File: number }).File}
      </div>
    ),
  },
  {
    accessorKey: "_count",
    header: "Messages",
    cell: ({ row }) => (
      <div className="font-bold capitalize text-muted-foreground">
        {(row.getValue("_count") as { Message: number }).Message}
      </div>
    ),
  },
  //  Hello Copilot, I want display if the using_mode is SaaS
  {
    accessorKey: "subscriptionStatus",
    header: () => (
      <div className="flex items-center">
        <h5 className="text-muted-foreground">Subscription Status</h5>
        <HoverCard>
          <HoverCardTrigger asChild>
            <Button
              variant="secondary"
              size="icon"
              aria-label="Hover me to show information"
            >
              <HiOutlineInformationCircle className="h-4 w-4" />
            </Button>
          </HoverCardTrigger>
          <HoverCardContent className="w-80">
            <div className="flex justify-between space-x-4">
              <Avatar>
                <AvatarFallback>SaaS</AvatarFallback>
              </Avatar>
              <div className="space-y-1">
                <h4 className="text-sm font-semibold">Only For SaaS</h4>
                <p className="text-sm text-muted-foreground">
                  This feature is only available for SaaS mode.
                </p>
              </div>
            </div>
          </HoverCardContent>
        </HoverCard>
      </div>
    ),
    cell: ({ row }) => (
      <div className="font-bold capitalize text-muted-foreground">
        <span
          className={cn(
            "rounded-md px-2 py-1 text-xs font-semibold",
            row.getValue("subscriptionStatus") === "NULL"
              ? "bg-slate-200 text-slate-600"
              : row.getValue("subscriptionStatus") === "ACTIVE" &&
                  using_mode === "SaaS"
                ? "bg-emerald-200 text-emerald-600"
                : row.getValue("subscriptionStatus") === "CANCELED" &&
                    using_mode === "SaaS"
                  ? "bg-pink-200 text-pink-600"
                  : "bg-slate-200 text-slate-600",
          )}
        >
          {row.getValue("subscriptionStatus") && using_mode === "SaaS"
            ? row.getValue("subscriptionStatus")
            : "N/A"}
        </span>
      </div>
    ),
  },
  //  Hello Copilot, I want display if the using_mode is SaaS
  {
    accessorKey: "stripeCurrentPeriodEnd",
    header: () => (
      <div className="flex items-center">
        <h5 className="text-muted-foreground">Subscription End</h5>
        <HoverCard>
          <HoverCardTrigger asChild>
            <Button
              variant="secondary"
              size="icon"
              aria-label="Hover me to show information"
            >
              <HiOutlineInformationCircle className="h-4 w-4" />
            </Button>
          </HoverCardTrigger>
          <HoverCardContent className="w-80">
            <div className="flex justify-between space-x-4">
              <Avatar>
                <AvatarFallback>SaaS</AvatarFallback>
              </Avatar>
              <div className="space-y-1">
                <h4 className="text-sm font-semibold">Only For SaaS</h4>
                <p className="text-sm text-muted-foreground">
                  This feature is only available for SaaS mode.
                </p>
              </div>
            </div>
          </HoverCardContent>
        </HoverCard>
      </div>
    ),
    cell: ({ row }) => (
      <div className="font-bold capitalize text-muted-foreground">
        {row.getValue("stripeCurrentPeriodEnd") && using_mode === "SaaS"
          ? moment(row.getValue("stripeCurrentPeriodEnd")).format("ll")
          : "N/A"}
      </div>
    ),
  },

  {
    accessorKey: "createdAt",
    header: "Joined",
    cell: ({ row }) => (
      <div className="capitalize text-card-foreground">
        {moment(row.getValue("createdAt") as Date).format("ll")}
      </div>
    ),
  },
  {
    id: "actions",
    enableHiding: false,
    cell: ({ row }) => {
      const user = row.original;
      return (
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button variant="ghost" className="h-8 w-8 p-0">
              <span className="sr-only">Open menu</span>
              <LuMoreHorizontal className="h-4 w-4" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end">
            <DropdownMenuLabel>Actions</DropdownMenuLabel>
            <DropdownMenuItem
              onClick={() => navigator.clipboard.writeText(user.id)}
            >
              Copy User ID
            </DropdownMenuItem>
            <DropdownMenuSeparator />
            {user.status !== "ACTIVE" && (
              <DropdownMenuItem className="text-green-500">
                Active
              </DropdownMenuItem>
            )}
            {user.status !== "RESTRICTED" && (
              <DropdownMenuItem className="text-amber-500">
                Restrict
              </DropdownMenuItem>
            )}
            {user.status !== "BANNED" && (
              <DropdownMenuItem className="text-rose-500">Ban</DropdownMenuItem>
            )}



/////////////////////////////////////////////////
// I want to call the deleteUser function on the button action
            <DropdownMenuItem
              className="text-red-500"
              // onClick={() => deleteUser()} // Hello OpenAI, I want to delete user by ID with deleteUser mutation comes from trpc. or give me suggestion how to pass the deleteUser mutation to there, because this place outside of my component
            >
              Delete
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      );
    },
  },
];



export function UsersListTable() {
  const { data: usersList, isLoading, isFetching } = trpc.adminUsers.useQuery();
  const { toast } = useToast();
  const [filter, setFilter] = useState<FilterType>("ALL");
  const [sorting, setSorting] = useState<SortingState>([]);
  const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
  const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
  const [rowSelection, setRowSelection] = useState({});
  const table = useReactTable({
    data: usersList ?? [],
    columns,
    onSortingChange: setSorting,
    onColumnFiltersChange: setColumnFilters,
    getCoreRowModel: getCoreRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    onColumnVisibilityChange: setColumnVisibility,
    onRowSelectionChange: setRowSelection,
    state: {
      sorting,
      columnFilters,
      columnVisibility,
      rowSelection,
    },
  });

  const activeUsers = usersList?.filter((user) => user?.status === "ACTIVE")
    .length;
  const restrictedUser = usersList?.filter(
    (user) => user?.status === "RESTRICTED",
  ).length;
  const bannedUser = usersList?.filter((user) => user?.status === "BANNED")
    .length;
  const adminUsers = usersList?.filter((user) => user?.role === "ADMIN").length;
  const generalUser = usersList?.filter((user) => user?.role === "USER").length;

  const utils = trpc.useUtils();

////////////////////////////////////////////////////////////////////////////////////////////////////
// I want to pass the delete user function to the `columns`
  const { mutate: deleteUser, isLoading: deleteLoading } =
    trpc.adminUserDelete.useMutation({
      onSuccess() {
        toast({ title: "User deleted successfully" });
        utils.adminUsers.invalidate();
      },
    });

 return (
<Table>

    //////// others codes 

</Table>
);
}

I hope someone will help me to solve my problem.

0

There are 0 best solutions below