feat: customer groups react hooks (#1153)
* fix: msw handlers for medusa-react storybook * feat: add customer groups query hooks * feat: add create/update customer groups hooks * feat: add customer group batch hooks * feat: add test files, fix import * add customer groups fixture * add customer gorup mock endpoints * add test cases * add hook comments * fix: typos * fix: comments refactor * fix: comment Co-authored-by: fPolic <frane@medusajs.com>
This commit is contained in:
@@ -17,7 +17,7 @@ class AdminCustomerGroupsResource extends BaseResource {
|
|||||||
/**
|
/**
|
||||||
* Create a customer group.
|
* Create a customer group.
|
||||||
*
|
*
|
||||||
* @param payload - Customer group info.
|
* @param payload - customer group info
|
||||||
* @param customHeaders
|
* @param customHeaders
|
||||||
*/
|
*/
|
||||||
create(
|
create(
|
||||||
@@ -44,8 +44,8 @@ class AdminCustomerGroupsResource extends BaseResource {
|
|||||||
/**
|
/**
|
||||||
* Updates a customer group
|
* Updates a customer group
|
||||||
*
|
*
|
||||||
* @param id customer group id
|
* @param id - customer group id
|
||||||
* @param payload data to update customer group with
|
* @param payload - data to update customer group with
|
||||||
* @param customHeaders
|
* @param customHeaders
|
||||||
*/
|
*/
|
||||||
update(
|
update(
|
||||||
@@ -102,7 +102,7 @@ class AdminCustomerGroupsResource extends BaseResource {
|
|||||||
id: string,
|
id: string,
|
||||||
payload: AdminPostCustomerGroupsGroupCustomersBatchReq,
|
payload: AdminPostCustomerGroupsGroupCustomersBatchReq,
|
||||||
customHeaders: Record<string, any> = {}
|
customHeaders: Record<string, any> = {}
|
||||||
): Promise<AdminCustomerGroupsRes> {
|
): ResponsePromise<AdminCustomerGroupsRes> {
|
||||||
const path = `/admin/customer-groups/${id}/customers/batch`
|
const path = `/admin/customer-groups/${id}/customers/batch`
|
||||||
return this.client.request("POST", path, payload, {}, customHeaders)
|
return this.client.request("POST", path, payload, {}, customHeaders)
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@ class AdminCustomerGroupsResource extends BaseResource {
|
|||||||
id: string,
|
id: string,
|
||||||
payload: AdminDeleteCustomerGroupsGroupCustomerBatchReq,
|
payload: AdminDeleteCustomerGroupsGroupCustomerBatchReq,
|
||||||
customHeaders: Record<string, any> = {}
|
customHeaders: Record<string, any> = {}
|
||||||
): Promise<AdminCustomerGroupsRes> {
|
): ResponsePromise<AdminCustomerGroupsRes> {
|
||||||
const path = `/admin/customer-groups/${id}/customers/batch`
|
const path = `/admin/customer-groups/${id}/customers/batch`
|
||||||
return this.client.request("DELETE", path, payload, {}, customHeaders)
|
return this.client.request("DELETE", path, payload, {}, customHeaders)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import DefaultMedusaProvider from "./medusa-context"
|
import DefaultMedusaProvider from "./medusa-context"
|
||||||
import { initialize, mswDecorator } from "msw-storybook-addon"
|
import { initialize, mswDecorator } from "msw-storybook-addon"
|
||||||
import { handlers } from "../mocks/handlers"
|
import { adminHandlers, storeHandlers } from "../mocks/handlers"
|
||||||
|
|
||||||
initialize()
|
initialize()
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ export const parameters = {
|
|||||||
// https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args
|
// https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args
|
||||||
actions: { argTypesRegex: "^on.*" },
|
actions: { argTypesRegex: "^on.*" },
|
||||||
msw: {
|
msw: {
|
||||||
handlers,
|
handlers: [...adminHandlers, ...storeHandlers],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -516,6 +516,14 @@
|
|||||||
"deleted_at": null,
|
"deleted_at": null,
|
||||||
"metadata": null
|
"metadata": null
|
||||||
},
|
},
|
||||||
|
"customer_group": {
|
||||||
|
"name": "test group",
|
||||||
|
"id": "cgrp_01FX8NJYPPDEH7YK9NYM6BXPHV",
|
||||||
|
"deleted_at": null,
|
||||||
|
"metadata": null,
|
||||||
|
"created_at": "2022-03-03T19:54:53.014Z",
|
||||||
|
"updated_at": "2022-03-03T19:54:53.014Z"
|
||||||
|
},
|
||||||
"shipping_profile": {
|
"shipping_profile": {
|
||||||
"id": "sp_01F0YESTZQFW15SFEZSS29EZ5R",
|
"id": "sp_01F0YESTZQFW15SFEZSS29EZ5R",
|
||||||
"name": "Default Shipping Profile",
|
"name": "Default Shipping Profile",
|
||||||
|
|||||||
@@ -509,6 +509,48 @@ export const adminHandlers = [
|
|||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
rest.get("/admin/customer-groups/", (req, res, ctx) => {
|
||||||
|
return res(
|
||||||
|
ctx.status(200),
|
||||||
|
ctx.json({
|
||||||
|
customer_groups: fixtures.list("customer_group"),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
|
||||||
|
rest.get("/admin/customer-groups/:id", (req, res, ctx) => {
|
||||||
|
return res(
|
||||||
|
ctx.status(200),
|
||||||
|
ctx.json({
|
||||||
|
customer_group: fixtures.get("customer_group"),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
|
||||||
|
rest.post("/admin/customer-groups/", (req, res, ctx) => {
|
||||||
|
return res(
|
||||||
|
ctx.status(200),
|
||||||
|
ctx.json({
|
||||||
|
customer_group: {
|
||||||
|
...fixtures.get("customer_group"),
|
||||||
|
...(req.body as any),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
|
||||||
|
rest.post("/admin/customer-groups/:id", (req, res, ctx) => {
|
||||||
|
return res(
|
||||||
|
ctx.status(200),
|
||||||
|
ctx.json({
|
||||||
|
customer_group: {
|
||||||
|
...fixtures.get("customer_group"),
|
||||||
|
...(req.body as any),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
|
||||||
rest.get("/admin/discounts/", (req, res, ctx) => {
|
rest.get("/admin/discounts/", (req, res, ctx) => {
|
||||||
return res(
|
return res(
|
||||||
ctx.status(200),
|
ctx.status(200),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { setupServer } from "msw/node"
|
import { setupServer } from "msw/node"
|
||||||
import { storeHandlers, adminHandlers } from "./handlers"
|
import { storeHandlers, adminHandlers } from "./handlers"
|
||||||
|
|
||||||
export const server = setupServer(...[...storeHandlers, ...adminHandlers])
|
export const server = setupServer(...storeHandlers, ...adminHandlers)
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export * from "./queries"
|
||||||
|
export * from "./mutations"
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
import {
|
||||||
|
AdminCustomerGroupsRes,
|
||||||
|
AdminDeleteCustomerGroupsGroupCustomerBatchReq,
|
||||||
|
AdminPostCustomerGroupsGroupCustomersBatchReq,
|
||||||
|
AdminPostCustomerGroupsGroupReq,
|
||||||
|
AdminPostCustomerGroupsReq,
|
||||||
|
} from "@medusajs/medusa"
|
||||||
|
import { useMutation, UseMutationOptions, useQueryClient } from "react-query"
|
||||||
|
import { Response } from "@medusajs/medusa-js"
|
||||||
|
|
||||||
|
import { useMedusa } from "../../../contexts/medusa"
|
||||||
|
import { buildOptions } from "../../utils/buildOptions"
|
||||||
|
import { adminCustomerGroupKeys } from "./queries"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook returns functions for creating customer groups.
|
||||||
|
*
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
export const useAdminCreateCustomerGroup = (
|
||||||
|
options?: UseMutationOptions<
|
||||||
|
Response<AdminCustomerGroupsRes>,
|
||||||
|
Error,
|
||||||
|
AdminPostCustomerGroupsReq
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
const { client } = useMedusa()
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
|
||||||
|
return useMutation(
|
||||||
|
(payload: AdminPostCustomerGroupsReq) =>
|
||||||
|
client.admin.customerGroups.create(payload),
|
||||||
|
buildOptions(queryClient, adminCustomerGroupKeys.lists(), options)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook return functions for updating a customer group.
|
||||||
|
*
|
||||||
|
* @param id - id of the customer group that is being updated
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
export const useAdminUpdateCustomerGroup = (
|
||||||
|
id: string,
|
||||||
|
options?: UseMutationOptions<
|
||||||
|
Response<AdminCustomerGroupsRes>,
|
||||||
|
Error,
|
||||||
|
AdminPostCustomerGroupsGroupReq
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
const { client } = useMedusa()
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
return useMutation(
|
||||||
|
(payload: AdminPostCustomerGroupsGroupReq) =>
|
||||||
|
client.admin.customerGroups.update(id, payload),
|
||||||
|
buildOptions(
|
||||||
|
queryClient,
|
||||||
|
[adminCustomerGroupKeys.lists(), adminCustomerGroupKeys.detail(id)],
|
||||||
|
options
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook returns functions for addition of multiple customers to a customer group.
|
||||||
|
*
|
||||||
|
* @param id - id of the customer group in which customers are being added
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
export const useAdminAddCustomersToCustomerGroup = (
|
||||||
|
id: string,
|
||||||
|
options?: UseMutationOptions<
|
||||||
|
Response<AdminCustomerGroupsRes>,
|
||||||
|
Error,
|
||||||
|
AdminPostCustomerGroupsGroupCustomersBatchReq
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
const { client } = useMedusa()
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
return useMutation(
|
||||||
|
(payload: AdminPostCustomerGroupsGroupCustomersBatchReq) =>
|
||||||
|
client.admin.customerGroups.addCustomers(id, payload),
|
||||||
|
buildOptions(
|
||||||
|
queryClient,
|
||||||
|
[adminCustomerGroupKeys.lists(), adminCustomerGroupKeys.detail(id)],
|
||||||
|
options
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook returns function for removal of multiple customers from a customer group.
|
||||||
|
*
|
||||||
|
* @param id - id of a group from which customers will be removed
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
export const useAdminRemoveCustomersFromCustomerGroup = (
|
||||||
|
id: string,
|
||||||
|
options?: UseMutationOptions<
|
||||||
|
Response<AdminCustomerGroupsRes>,
|
||||||
|
Error,
|
||||||
|
AdminDeleteCustomerGroupsGroupCustomerBatchReq
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
const { client } = useMedusa()
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
return useMutation(
|
||||||
|
(payload: AdminDeleteCustomerGroupsGroupCustomerBatchReq) =>
|
||||||
|
client.admin.customerGroups.removeCustomers(id, payload),
|
||||||
|
buildOptions(
|
||||||
|
queryClient,
|
||||||
|
[adminCustomerGroupKeys.lists(), adminCustomerGroupKeys.detail(id)],
|
||||||
|
options
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
import {
|
||||||
|
AdminCustomerGroupsListRes,
|
||||||
|
AdminCustomerGroupsRes,
|
||||||
|
AdminGetCustomerGroupsParams,
|
||||||
|
} from "@medusajs/medusa"
|
||||||
|
import { Response } from "@medusajs/medusa-js"
|
||||||
|
import { useQuery } from "react-query"
|
||||||
|
|
||||||
|
import { useMedusa } from "../../../contexts"
|
||||||
|
import { UseQueryOptionsWrapper } from "../../../types"
|
||||||
|
import { queryKeysFactory } from "../../utils/index"
|
||||||
|
|
||||||
|
const ADMIN_CUSTOMER_GROUPS_QUERY_KEY = `admin_customer_groups` as const
|
||||||
|
|
||||||
|
export const adminCustomerGroupKeys = queryKeysFactory(
|
||||||
|
ADMIN_CUSTOMER_GROUPS_QUERY_KEY
|
||||||
|
)
|
||||||
|
|
||||||
|
type CustomerGroupQueryKeys = typeof adminCustomerGroupKeys
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook retrieves a customer group by id.
|
||||||
|
*
|
||||||
|
* @param id - customer group id
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
export const useAdminCustomerGroup = (
|
||||||
|
id: string,
|
||||||
|
options?: UseQueryOptionsWrapper<
|
||||||
|
Response<AdminCustomerGroupsRes>,
|
||||||
|
Error,
|
||||||
|
ReturnType<CustomerGroupQueryKeys["detail"]>
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
const { client } = useMedusa()
|
||||||
|
const { data, ...rest } = useQuery(
|
||||||
|
adminCustomerGroupKeys.detail(id),
|
||||||
|
() => client.admin.customerGroups.retrieve(id),
|
||||||
|
options
|
||||||
|
)
|
||||||
|
return { ...data, ...rest } as const
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook retrieves a list of customer gorups.
|
||||||
|
*
|
||||||
|
* @param query - pagination/filtering params
|
||||||
|
* @param options
|
||||||
|
*/
|
||||||
|
export const useAdminCustomerGroups = (
|
||||||
|
query?: AdminGetCustomerGroupsParams,
|
||||||
|
options?: UseQueryOptionsWrapper<
|
||||||
|
Response<AdminCustomerGroupsListRes>,
|
||||||
|
Error,
|
||||||
|
ReturnType<CustomerGroupQueryKeys["list"]>
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
const { client } = useMedusa()
|
||||||
|
const { data, ...rest } = useQuery(
|
||||||
|
adminCustomerGroupKeys.list(query),
|
||||||
|
() => client.admin.customerGroups.list(query),
|
||||||
|
options
|
||||||
|
)
|
||||||
|
return { ...data, ...rest } as const
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ export * from "./auth"
|
|||||||
export * from "./collections"
|
export * from "./collections"
|
||||||
export * from "./claims"
|
export * from "./claims"
|
||||||
export * from "./customers"
|
export * from "./customers"
|
||||||
|
export * from "./customer-groups"
|
||||||
export * from "./discounts"
|
export * from "./discounts"
|
||||||
export * from "./draft-orders"
|
export * from "./draft-orders"
|
||||||
export * from "./gift-cards"
|
export * from "./gift-cards"
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { renderHook } from "@testing-library/react-hooks"
|
||||||
|
|
||||||
|
import {
|
||||||
|
useAdminCreateCustomerGroup,
|
||||||
|
useAdminUpdateCustomerGroup,
|
||||||
|
} from "../../../../src/"
|
||||||
|
import { fixtures } from "../../../../mocks/data"
|
||||||
|
import { createWrapper } from "../../../utils"
|
||||||
|
|
||||||
|
describe("useAdminCreateCustomerGroup hook", () => {
|
||||||
|
test("creates a customer group and returns it", async () => {
|
||||||
|
const group = {
|
||||||
|
name: "Group 1",
|
||||||
|
}
|
||||||
|
|
||||||
|
const { result, waitFor } = renderHook(
|
||||||
|
() => useAdminCreateCustomerGroup(),
|
||||||
|
{
|
||||||
|
wrapper: createWrapper(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
result.current.mutate(group)
|
||||||
|
|
||||||
|
await waitFor(() => result.current.isSuccess)
|
||||||
|
|
||||||
|
expect(result.current.data.response.status).toEqual(200)
|
||||||
|
expect(result.current.data.customer_group).toEqual(
|
||||||
|
expect.objectContaining(group)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("useAdminUpdateCustomerGroup hook", () => {
|
||||||
|
test("updates a customer group and returns it", async () => {
|
||||||
|
const group = {
|
||||||
|
name: "Changeed name",
|
||||||
|
}
|
||||||
|
|
||||||
|
const { result, waitFor } = renderHook(
|
||||||
|
() => useAdminUpdateCustomerGroup(fixtures.get("customer_group").id),
|
||||||
|
{
|
||||||
|
wrapper: createWrapper(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
result.current.mutate(group)
|
||||||
|
|
||||||
|
await waitFor(() => result.current.isSuccess)
|
||||||
|
|
||||||
|
expect(result.current.data.response.status).toEqual(200)
|
||||||
|
expect(result.current.data.customer_group).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
...fixtures.get("customer_group"),
|
||||||
|
...group,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { renderHook } from "@testing-library/react-hooks"
|
||||||
|
|
||||||
|
import { useAdminCustomerGroup, useAdminCustomerGroups } from "../../../../src"
|
||||||
|
import { fixtures } from "../../../../mocks/data"
|
||||||
|
import { createWrapper } from "../../../utils"
|
||||||
|
|
||||||
|
describe("useAdminCustomerGroup hook", () => {
|
||||||
|
test("returns a customer group", async () => {
|
||||||
|
const group = fixtures.get("customer_group")
|
||||||
|
const { result, waitFor } = renderHook(
|
||||||
|
() => useAdminCustomerGroup(group.id),
|
||||||
|
{
|
||||||
|
wrapper: createWrapper(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
await waitFor(() => result.current.isSuccess)
|
||||||
|
|
||||||
|
expect(result.current.response.status).toEqual(200)
|
||||||
|
expect(result.current.customer_group).toEqual(group)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns a list of customer groups", async () => {
|
||||||
|
const groups = fixtures.list("customer_group")
|
||||||
|
const { result, waitFor } = renderHook(() => useAdminCustomerGroups(), {
|
||||||
|
wrapper: createWrapper(),
|
||||||
|
})
|
||||||
|
|
||||||
|
await waitFor(() => result.current.isSuccess)
|
||||||
|
|
||||||
|
expect(result.current.response.status).toEqual(200)
|
||||||
|
expect(result.current.customer_groups).toEqual(groups)
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user