import { PencilSquare, Trash } from "@medusajs/icons"
import { HttpTypes } from "@medusajs/types"
import {
Container,
createDataTableColumnHelper,
toast,
usePrompt,
} from "@medusajs/ui"
import { keepPreviousData } from "@tanstack/react-query"
import { useCallback, useMemo } from "react"
import { useTranslation } from "react-i18next"
import { useNavigate } from "react-router-dom"
import { DataTable } from "../../../../../components/data-table"
import { useDataTableDateFilters } from "../../../../../components/data-table/helpers/general/use-data-table-date-filters"
import { ListSummary } from "../../../../../components/common/list-summary"
import {
useDeleteRbacRoleLazy,
useRbacRoles,
} from "../../../../../hooks/api/rbac-roles"
import { useDate } from "../../../../../hooks/use-date"
import { useQueryParams } from "../../../../../hooks/use-query-params"
import type { Permission } from "../../../../../lib/permissions"
import { usePermissions } from "../../../../../providers/permissions-provider"
const PAGE_SIZE = 20
export const RoleListTable = () => {
const { t } = useTranslation()
const { hasPermission } = usePermissions()
const { q, order, offset, created_at } = useQueryParams([
"q",
"order",
"offset",
"created_at",
])
const { roles, count, isPending, isError, error } = useRbacRoles(
{
q,
order,
offset: offset ? parseInt(offset) : undefined,
limit: PAGE_SIZE,
created_at: created_at ? JSON.parse(created_at) : undefined,
fields:
"id,name,description,created_at,users.id,users.first_name,users.last_name,users.email",
},
{
placeholderData: keepPreviousData,
}
)
const columns = useColumns({ hasPermission })
const filters = useFilters()
if (isError) {
throw error
}
const canCreate = hasPermission("rbac_role:create")
return (
row.id}
rowHref={(row) => `${row.id}`}
rowCount={count}
pageSize={PAGE_SIZE}
heading={t("roles.domain")}
subHeading={t("roles.subtitle")}
isLoading={isPending}
action={
canCreate
? {
label: t("actions.create"),
to: "create",
}
: undefined
}
emptyState={{
empty: {
heading: t("roles.list.empty.heading"),
description: t("roles.list.empty.description"),
},
filtered: {
heading: t("roles.list.filtered.heading"),
description: t("roles.list.filtered.description"),
},
}}
/>
)
}
type RoleWithUsers = HttpTypes.AdminRbacRole & {
users_link?: { user?: HttpTypes.AdminUser | null }[]
}
const columnHelper = createDataTableColumnHelper()
const useColumns = ({
hasPermission,
}: {
hasPermission: (permission: Permission) => boolean
}) => {
const { t } = useTranslation()
const navigate = useNavigate()
const prompt = usePrompt()
const { getFullDate } = useDate()
const { mutateAsync: deleteRole } = useDeleteRbacRoleLazy()
const handleEdit = useCallback(
(role: HttpTypes.AdminRbacRole) => {
navigate(`/settings/roles/${role.id}/edit`)
},
[navigate]
)
const handleDelete = useCallback(
async (role: HttpTypes.AdminRbacRole) => {
const confirmed = await prompt({
title: t("roles.delete.title"),
description: t("roles.delete.description", { name: role.name }),
confirmText: t("actions.delete"),
cancelText: t("actions.cancel"),
})
if (!confirmed) {
return
}
try {
await deleteRole(role.id)
toast.success(t("roles.delete.successToast", { name: role.name }))
} catch (error) {
toast.error((error as Error).message)
}
},
[prompt, deleteRole, t]
)
const canUpdate = hasPermission("rbac_role:update")
const canDelete = hasPermission("rbac_role:delete")
return useMemo(() => {
const baseColumns = [
columnHelper.accessor("name", {
header: t("fields.name"),
enableSorting: true,
sortAscLabel: t("filters.sorting.alphabeticallyAsc"),
sortDescLabel: t("filters.sorting.alphabeticallyDesc"),
}),
columnHelper.accessor("description", {
header: t("fields.description"),
cell: ({ row }) => {
return row.original.description || "-"
},
}),
columnHelper.display({
id: "users",
header: t("users.domain"),
cell: ({ row }) => {
const users =
row.original.users_link
?.map((link) => link.user)
.filter((user): user is HttpTypes.AdminUser => !!user) ?? []
if (!users.length) {
return "-"
}
const labels = users.map((user) => {
const fullName = `${user.first_name || ""} ${
user.last_name || ""
}`.trim()
return fullName || user.email || user.id
})
return (
)
},
}),
columnHelper.accessor("created_at", {
header: t("fields.createdAt"),
cell: ({ row }) => {
return {getFullDate({ date: row.original.created_at })}
},
enableSorting: true,
sortAscLabel: t("filters.sorting.dateAsc"),
sortDescLabel: t("filters.sorting.dateDesc"),
}),
]
if (!canUpdate && !canDelete) {
return baseColumns
}
const groups: {
label: string
icon: React.ReactNode
onClick: (ctx: { row: { original: HttpTypes.AdminRbacRole } }) => void
}[][] = []
if (canUpdate) {
groups.push([
{
label: t("actions.edit"),
icon: ,
onClick: (ctx) => handleEdit(ctx.row.original),
},
])
}
if (canDelete) {
groups.push([
{
label: t("actions.delete"),
icon: ,
onClick: (ctx) => handleDelete(ctx.row.original),
},
])
}
return [
...baseColumns,
columnHelper.action({
actions: groups,
}),
]
}, [t, getFullDate, handleEdit, handleDelete, canUpdate, canDelete])
}
const useFilters = () => {
const dateFilters = useDataTableDateFilters()
return useMemo(() => {
return dateFilters.filter((filter) => filter.id === "created_at")
}, [dateFilters])
}