Skip to content

Commit

Permalink
refactor: users domain (#7070)
Browse files Browse the repository at this point in the history
**What**
- refactor users domain to use `DataTable`
- add search params to `User` module models
  • Loading branch information
fPolic committed Apr 16, 2024
1 parent a7df623 commit 122b3ea
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 88 deletions.
@@ -1,15 +1,15 @@
import { AdminGetSalesChannelsParams } from "@medusajs/medusa"
import { useQueryParams } from "../../use-query-params"

type UseCustomerTableQueryProps = {
type UseSalesChannelTableQueryProps = {
prefix?: string
pageSize?: number
}

export const useSalesChannelTableQuery = ({
prefix,
pageSize = 20,
}: UseCustomerTableQueryProps) => {
}: UseSalesChannelTableQueryProps) => {
const queryObject = useQueryParams(
["offset", "q", "order", "created_at", "updated_at"],
prefix
Expand Down
@@ -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,
}
}
Expand Up @@ -8,7 +8,12 @@ export const UserDetail = () => {
const initialData = useLoaderData() as Awaited<ReturnType<typeof userLoader>>

const { id } = useParams()
const { user, isLoading, isError, error } = useUser(id!, undefined, {
const {
user,
isPending: isLoading,
isError,
error,
} = useUser(id!, undefined, {
initialData,
})

Expand Down
Expand Up @@ -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
Expand Down
Expand Up @@ -7,41 +7,35 @@ 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,
useDeleteInvite,
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()
Expand All @@ -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()
Expand Down Expand Up @@ -136,68 +138,18 @@ export const InviteUserForm = () => {
<div className="flex flex-col gap-y-4">
<Heading level="h2">{t("users.pendingInvites")}</Heading>
<Container className="overflow-hidden p-0">
{!noRecords ? (
<div>
<Table>
<Table.Header className="border-t-0">
{table.getHeaderGroups().map((headerGroup) => {
return (
<Table.Row
key={headerGroup.id}
className="[&_th:last-of-type]:w-[1%] [&_th:last-of-type]:whitespace-nowrap [&_th]:w-1/3"
>
{headerGroup.headers.map((header) => {
return (
<Table.HeaderCell key={header.id}>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
</Table.HeaderCell>
)
})}
</Table.Row>
)
})}
</Table.Header>
<Table.Body>
{table.getRowModel().rows.map((row) => (
<Table.Row
key={row.id}
className={clx(
"transition-fg[&_td:last-of-type]:w-[1%] [&_td:last-of-type]:whitespace-nowrap",
{
"bg-ui-bg-highlight hover:bg-ui-bg-highlight-hover":
row.getIsSelected(),
}
)}
>
{row.getVisibleCells().map((cell) => (
<Table.Cell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</Table.Cell>
))}
</Table.Row>
))}
</Table.Body>
</Table>
<LocalizedTablePagination
canNextPage={table.getCanNextPage()}
canPreviousPage={table.getCanPreviousPage()}
nextPage={table.nextPage}
previousPage={table.previousPage}
count={count}
pageIndex={table.getState().pagination.pageIndex}
pageCount={table.getPageCount()}
pageSize={PAGE_SIZE}
/>
</div>
) : (
<NoRecords className="h-[200px]" />
)}
<DataTable
table={table}
columns={columns}
count={count}
pageSize={PAGE_SIZE}
prefix={PREFIX}
pagination
search
isLoading={isLoading}
queryObject={raw}
orderBy={["email", "created_at", "updated_at"]}
/>
</Container>
</div>
</div>
Expand Down
Expand Up @@ -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,
})

Expand Down
7 changes: 7 additions & 0 deletions packages/medusa/src/api-v2/admin/invites/validators.ts
Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions packages/medusa/src/api-v2/admin/users/validators.ts
Expand Up @@ -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(),
})
)

Expand Down
2 changes: 2 additions & 0 deletions packages/user/src/models/invite.ts
Expand Up @@ -14,6 +14,7 @@ import {
DALUtils,
createPsqlIndexStatementHelper,
generateEntityId,
Searchable,
} from "@medusajs/utils"

const inviteEmailIndexName = "IDX_invite_email"
Expand Down Expand Up @@ -57,6 +58,7 @@ export default class Invite {
name: inviteEmailIndexName,
expression: inviteEmailIndexStatement,
})
@Searchable()
@Property({ columnType: "text" })
email: string

Expand Down
6 changes: 5 additions & 1 deletion packages/user/src/models/user.ts
Expand Up @@ -14,6 +14,7 @@ import {
DALUtils,
createPsqlIndexStatementHelper,
generateEntityId,
Searchable,
} from "@medusajs/utils"

const userEmailIndexName = "IDX_user_email"
Expand Down Expand Up @@ -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 })
Expand Down

0 comments on commit 122b3ea

Please sign in to comment.