diff --git a/packages/admin-next/dashboard/src/hooks/table/query/use-sales-channel-table-query.tsx b/packages/admin-next/dashboard/src/hooks/table/query/use-sales-channel-table-query.tsx index 222b4199cc..53299b2c19 100644 --- a/packages/admin-next/dashboard/src/hooks/table/query/use-sales-channel-table-query.tsx +++ b/packages/admin-next/dashboard/src/hooks/table/query/use-sales-channel-table-query.tsx @@ -1,7 +1,7 @@ import { AdminGetSalesChannelsParams } from "@medusajs/medusa" import { useQueryParams } from "../../use-query-params" -type UseCustomerTableQueryProps = { +type UseSalesChannelTableQueryProps = { prefix?: string pageSize?: number } @@ -9,7 +9,7 @@ type UseCustomerTableQueryProps = { export const useSalesChannelTableQuery = ({ prefix, pageSize = 20, -}: UseCustomerTableQueryProps) => { +}: UseSalesChannelTableQueryProps) => { const queryObject = useQueryParams( ["offset", "q", "order", "created_at", "updated_at"], prefix diff --git a/packages/admin-next/dashboard/src/hooks/table/query/use-user-invite-table-query.tsx b/packages/admin-next/dashboard/src/hooks/table/query/use-user-invite-table-query.tsx new file mode 100644 index 0000000000..356991a652 --- /dev/null +++ b/packages/admin-next/dashboard/src/hooks/table/query/use-user-invite-table-query.tsx @@ -0,0 +1,32 @@ +import { useQueryParams } from "../../use-query-params" + +type UseUserInviteTableQueryProps = { + prefix?: string + pageSize?: number +} + +export const useUserInviteTableQuery = ({ + prefix, + pageSize = 20, +}: UseUserInviteTableQueryProps) => { + const queryObject = useQueryParams( + ["offset", "q", "order", "created_at", "updated_at"], + prefix + ) + + const { offset, created_at, updated_at, q, order } = queryObject + + const searchParams = { + limit: pageSize, + offset: offset ? Number(offset) : 0, + order, + created_at: created_at ? JSON.parse(created_at) : undefined, + updated_at: updated_at ? JSON.parse(updated_at) : undefined, + q, + } + + return { + searchParams, + raw: queryObject, + } +} diff --git a/packages/admin-next/dashboard/src/v2-routes/users/user-detail/user-detail.tsx b/packages/admin-next/dashboard/src/v2-routes/users/user-detail/user-detail.tsx index 8b8ffc0ab9..66df154209 100644 --- a/packages/admin-next/dashboard/src/v2-routes/users/user-detail/user-detail.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/users/user-detail/user-detail.tsx @@ -8,7 +8,12 @@ export const UserDetail = () => { const initialData = useLoaderData() as Awaited> const { id } = useParams() - const { user, isLoading, isError, error } = useUser(id!, undefined, { + const { + user, + isPending: isLoading, + isError, + error, + } = useUser(id!, undefined, { initialData, }) diff --git a/packages/admin-next/dashboard/src/v2-routes/users/user-edit/user-edit.tsx b/packages/admin-next/dashboard/src/v2-routes/users/user-edit/user-edit.tsx index 8822dbf8d2..efe740f611 100644 --- a/packages/admin-next/dashboard/src/v2-routes/users/user-edit/user-edit.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/users/user-edit/user-edit.tsx @@ -8,7 +8,7 @@ import { EditUserForm } from "./components/edit-user-form" export const UserEdit = () => { const { t } = useTranslation() const { id } = useParams() - const { user, isLoading, isError, error } = useUser(id!) + const { user, isPending: isLoading, isError, error } = useUser(id!) if (isError) { throw error diff --git a/packages/admin-next/dashboard/src/v2-routes/users/user-invite/components/invite-user-form/invite-user-form.tsx b/packages/admin-next/dashboard/src/v2-routes/users/user-invite/components/invite-user-form/invite-user-form.tsx index 6204c214d0..564930cc0e 100644 --- a/packages/admin-next/dashboard/src/v2-routes/users/user-invite/components/invite-user-form/invite-user-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/users/user-invite/components/invite-user-form/invite-user-form.tsx @@ -7,28 +7,19 @@ import { Heading, Input, StatusBadge, - Table, Text, Tooltip, - clx, usePrompt, } from "@medusajs/ui" -import { - createColumnHelper, - flexRender, - getCoreRowModel, - getPaginationRowModel, - useReactTable, -} from "@tanstack/react-table" +import { createColumnHelper } from "@tanstack/react-table" import { format } from "date-fns" import { useMemo } from "react" import { useForm } from "react-hook-form" import { Trans, useTranslation } from "react-i18next" import * as zod from "zod" import { ActionMenu } from "../../../../../components/common/action-menu" -import { NoRecords } from "../../../../../components/common/empty-table-content" +import { useDataTable } from "../../../../../hooks/use-data-table" import { Form } from "../../../../../components/common/form" -import { LocalizedTablePagination } from "../../../../../components/localization/localized-table-pagination" import { RouteFocusModal } from "../../../../../components/route-modal" import { useCreateInvite, @@ -36,12 +27,15 @@ import { useInvites, useResendInvite, } from "../../../../../hooks/api/invites" +import { DataTable } from "../../../../../components/table/data-table" +import { useUserInviteTableQuery } from "../../../../../hooks/table/query/use-user-invite-table-query" const InviteUserSchema = zod.object({ email: zod.string().email(), }) const PAGE_SIZE = 10 +const PREFIX = "usr_invite" export const InviteUserForm = () => { const { t } = useTranslation() @@ -53,20 +47,28 @@ export const InviteUserForm = () => { resolver: zodResolver(InviteUserSchema), }) - const { invites, isLoading, isError, error } = useInvites() - const count = invites?.length ?? 0 + const { raw, searchParams } = useUserInviteTableQuery({ + prefix: PREFIX, + pageSize: PAGE_SIZE, + }) - const noRecords = !isLoading && count === 0 + const { + invites, + count, + isPending: isLoading, + isError, + error, + } = useInvites(searchParams) const columns = useColumns() - const table = useReactTable({ - // TODO: Update type when medusa-react is 2.0 compatible - data: (invites ?? []) as unknown as InviteDTO[], + const { table } = useDataTable({ + data: (invites ?? []) as InviteDTO[], columns, - pageCount: Math.ceil(count / PAGE_SIZE), - getCoreRowModel: getCoreRowModel(), - getPaginationRowModel: getPaginationRowModel(), + count, + enablePagination: true, + getRowId: (row) => row.id, + pageSize: PAGE_SIZE, }) const { mutateAsync, isPending } = useCreateInvite() @@ -136,68 +138,18 @@ export const InviteUserForm = () => {
{t("users.pendingInvites")} - {!noRecords ? ( -
- - - {table.getHeaderGroups().map((headerGroup) => { - return ( - - {headerGroup.headers.map((header) => { - return ( - - {flexRender( - header.column.columnDef.header, - header.getContext() - )} - - ) - })} - - ) - })} - - - {table.getRowModel().rows.map((row) => ( - - {row.getVisibleCells().map((cell) => ( - - {flexRender( - cell.column.columnDef.cell, - cell.getContext() - )} - - ))} - - ))} - -
- -
- ) : ( - - )} +
diff --git a/packages/admin-next/dashboard/src/v2-routes/users/user-list/components/user-list-table/user-list-table.tsx b/packages/admin-next/dashboard/src/v2-routes/users/user-list/components/user-list-table/user-list-table.tsx index 62fa9b9363..cd3b576035 100644 --- a/packages/admin-next/dashboard/src/v2-routes/users/user-list/components/user-list-table/user-list-table.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/users/user-list/components/user-list-table/user-list-table.tsx @@ -14,7 +14,13 @@ export const UserListTable = () => { const { raw, searchParams } = useUserTableQuery({ pageSize: PAGE_SIZE, }) - const { users, count, isLoading, isError, error } = useUsers(searchParams, { + const { + users, + count, + isPending: isLoading, + isError, + error, + } = useUsers(searchParams, { placeholderData: keepPreviousData, }) diff --git a/packages/medusa/src/api-v2/admin/invites/validators.ts b/packages/medusa/src/api-v2/admin/invites/validators.ts index 1ea4ee94eb..8b690c14bc 100644 --- a/packages/medusa/src/api-v2/admin/invites/validators.ts +++ b/packages/medusa/src/api-v2/admin/invites/validators.ts @@ -70,6 +70,13 @@ export class AdminGetInvitesParams extends extendedFindParamsMixin({ @IsOptional() @IsString() fields?: string + + /** + * The term to search invites emails. + */ + @IsString() + @IsOptional() + q?: string } export class AdminCreateInviteRequest { diff --git a/packages/medusa/src/api-v2/admin/users/validators.ts b/packages/medusa/src/api-v2/admin/users/validators.ts index 4d413d6bb0..d38ef5d6a1 100644 --- a/packages/medusa/src/api-v2/admin/users/validators.ts +++ b/packages/medusa/src/api-v2/admin/users/validators.ts @@ -20,6 +20,7 @@ export const AdminGetUsersParams = createFindParams({ email: z.string().optional(), first_name: z.string().optional(), last_name: z.string().optional(), + q: z.string().optional(), }) ) diff --git a/packages/user/src/models/invite.ts b/packages/user/src/models/invite.ts index 12661b57f8..503cb2ebe1 100644 --- a/packages/user/src/models/invite.ts +++ b/packages/user/src/models/invite.ts @@ -14,6 +14,7 @@ import { DALUtils, createPsqlIndexStatementHelper, generateEntityId, + Searchable, } from "@medusajs/utils" const inviteEmailIndexName = "IDX_invite_email" @@ -57,6 +58,7 @@ export default class Invite { name: inviteEmailIndexName, expression: inviteEmailIndexStatement, }) + @Searchable() @Property({ columnType: "text" }) email: string diff --git a/packages/user/src/models/user.ts b/packages/user/src/models/user.ts index dd4882cefc..ca1ba27a95 100644 --- a/packages/user/src/models/user.ts +++ b/packages/user/src/models/user.ts @@ -14,6 +14,7 @@ import { DALUtils, createPsqlIndexStatementHelper, generateEntityId, + Searchable, } from "@medusajs/utils" const userEmailIndexName = "IDX_user_email" @@ -47,17 +48,20 @@ export default class User { @PrimaryKey({ columnType: "text" }) id!: string + @Searchable() @Property({ columnType: "text", nullable: true }) first_name: string | null = null + @Searchable() @Property({ columnType: "text", nullable: true }) last_name: string | null = null - @Property({ columnType: "text" }) @Index({ name: userEmailIndexName, expression: userEmailIndexStatement, }) + @Searchable() + @Property({ columnType: "text" }) email: string @Property({ columnType: "text", nullable: true })