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:
Frane Polić
2022-03-07 12:52:48 +01:00
committed by GitHub
parent a6f352d9f1
commit daf49bcaf3
11 changed files with 335 additions and 8 deletions

View File

@@ -17,7 +17,7 @@ class AdminCustomerGroupsResource extends BaseResource {
/**
* Create a customer group.
*
* @param payload - Customer group info.
* @param payload - customer group info
* @param customHeaders
*/
create(
@@ -44,8 +44,8 @@ class AdminCustomerGroupsResource extends BaseResource {
/**
* Updates a customer group
*
* @param id customer group id
* @param payload data to update customer group with
* @param id - customer group id
* @param payload - data to update customer group with
* @param customHeaders
*/
update(
@@ -102,7 +102,7 @@ class AdminCustomerGroupsResource extends BaseResource {
id: string,
payload: AdminPostCustomerGroupsGroupCustomersBatchReq,
customHeaders: Record<string, any> = {}
): Promise<AdminCustomerGroupsRes> {
): ResponsePromise<AdminCustomerGroupsRes> {
const path = `/admin/customer-groups/${id}/customers/batch`
return this.client.request("POST", path, payload, {}, customHeaders)
}
@@ -118,7 +118,7 @@ class AdminCustomerGroupsResource extends BaseResource {
id: string,
payload: AdminDeleteCustomerGroupsGroupCustomerBatchReq,
customHeaders: Record<string, any> = {}
): Promise<AdminCustomerGroupsRes> {
): ResponsePromise<AdminCustomerGroupsRes> {
const path = `/admin/customer-groups/${id}/customers/batch`
return this.client.request("DELETE", path, payload, {}, customHeaders)
}

View File

@@ -1,7 +1,7 @@
import React from "react"
import DefaultMedusaProvider from "./medusa-context"
import { initialize, mswDecorator } from "msw-storybook-addon"
import { handlers } from "../mocks/handlers"
import { adminHandlers, storeHandlers } from "../mocks/handlers"
initialize()
@@ -10,7 +10,7 @@ export const parameters = {
// https://storybook.js.org/docs/react/essentials/actions#automatically-matching-args
actions: { argTypesRegex: "^on.*" },
msw: {
handlers,
handlers: [...adminHandlers, ...storeHandlers],
},
}

View File

@@ -516,6 +516,14 @@
"deleted_at": 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": {
"id": "sp_01F0YESTZQFW15SFEZSS29EZ5R",
"name": "Default Shipping Profile",

View File

@@ -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) => {
return res(
ctx.status(200),

View File

@@ -1,4 +1,4 @@
import { setupServer } from "msw/node"
import { storeHandlers, adminHandlers } from "./handlers"
export const server = setupServer(...[...storeHandlers, ...adminHandlers])
export const server = setupServer(...storeHandlers, ...adminHandlers)

View File

@@ -0,0 +1,2 @@
export * from "./queries"
export * from "./mutations"

View File

@@ -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
)
)
}

View File

@@ -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
}

View File

@@ -2,6 +2,7 @@ export * from "./auth"
export * from "./collections"
export * from "./claims"
export * from "./customers"
export * from "./customer-groups"
export * from "./discounts"
export * from "./draft-orders"
export * from "./gift-cards"

View File

@@ -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,
})
)
})
})
})

View File

@@ -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)
})
})