From c26b1d30b6d54f5aadf46c665852c97d05a2f038 Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Fri, 1 Nov 2024 11:16:11 +1300 Subject: [PATCH 1/5] Expose reason options --- .../ReasonOption/api/operations.generated.ts | 56 +++++++++++++++++++ .../src/ReasonOption/api/operations.graphql | 27 +++++++++ 2 files changed, 83 insertions(+) create mode 100644 client/packages/system/src/ReasonOption/api/operations.generated.ts create mode 100644 client/packages/system/src/ReasonOption/api/operations.graphql diff --git a/client/packages/system/src/ReasonOption/api/operations.generated.ts b/client/packages/system/src/ReasonOption/api/operations.generated.ts new file mode 100644 index 0000000000..9a29246286 --- /dev/null +++ b/client/packages/system/src/ReasonOption/api/operations.generated.ts @@ -0,0 +1,56 @@ +import * as Types from '@openmsupply-client/common'; + +import { GraphQLClient, RequestOptions } from 'graphql-request'; +import gql from 'graphql-tag'; +type GraphQLClientRequestHeaders = RequestOptions['requestHeaders']; +export type ReasonOptionRowFragment = { __typename: 'ReasonOptionNode', id: string, type: Types.ReasonOptionNodeType, reason: string, isActive: boolean }; + +export type ReasonOptionsQueryVariables = Types.Exact<{ + sort?: Types.InputMaybe | Types.ReasonOptionSortInput>; + filter?: Types.InputMaybe; +}>; + + +export type ReasonOptionsQuery = { __typename: 'Queries', reasonOptions: { __typename: 'ReasonOptionConnector', totalCount: number, nodes: Array<{ __typename: 'ReasonOptionNode', id: string, type: Types.ReasonOptionNodeType, reason: string, isActive: boolean }> } }; + +export const ReasonOptionRowFragmentDoc = gql` + fragment ReasonOptionRow on ReasonOptionNode { + __typename + id + type + reason + isActive +} + `; +export const ReasonOptionsDocument = gql` + query reasonOptions($sort: [ReasonOptionSortInput!], $filter: ReasonOptionFilterInput) { + reasonOptions(sort: $sort, filter: $filter) { + __typename + ... on ReasonOptionConnector { + __typename + totalCount + nodes { + __typename + id + type + reason + isActive + } + } + } +} + `; + +export type SdkFunctionWrapper = (action: (requestHeaders?:Record) => Promise, operationName: string, operationType?: string, variables?: any) => Promise; + + +const defaultWrapper: SdkFunctionWrapper = (action, _operationName, _operationType, _variables) => action(); + +export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper = defaultWrapper) { + return { + reasonOptions(variables?: ReasonOptionsQueryVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(ReasonOptionsDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'reasonOptions', 'query', variables); + } + }; +} +export type Sdk = ReturnType; \ No newline at end of file diff --git a/client/packages/system/src/ReasonOption/api/operations.graphql b/client/packages/system/src/ReasonOption/api/operations.graphql new file mode 100644 index 0000000000..06f087e687 --- /dev/null +++ b/client/packages/system/src/ReasonOption/api/operations.graphql @@ -0,0 +1,27 @@ +fragment ReasonOptionRow on ReasonOptionNode { + __typename + id + type + reason + isActive +} + +query reasonOptions( + $sort: [ReasonOptionSortInput!] + $filter: ReasonOptionFilterInput +) { + reasonOptions(sort: $sort, filter: $filter) { + __typename + ... on ReasonOptionConnector { + __typename + totalCount + nodes { + __typename + id + type + reason + isActive + } + } + } +} From b823dbb08be1bf32f248ac0bdd978c98fc528d40 Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Fri, 1 Nov 2024 11:19:33 +1300 Subject: [PATCH 2/5] Reason option hook to get all reasons --- .../src/ReasonOption/Components/index.ts | 1 + .../system/src/ReasonOption/api/api.ts | 31 +++++++++++++++++++ .../ReasonOption/api/hooks/document/index.ts | 5 +++ .../api/hooks/document/useReasonOptions.ts | 12 +++++++ .../src/ReasonOption/api/hooks/index.ts | 11 +++++++ .../src/ReasonOption/api/hooks/utils/index.ts | 5 +++ .../api/hooks/utils/useReasonOptionsApi.ts | 20 ++++++++++++ .../system/src/ReasonOption/api/index.ts | 2 ++ 8 files changed, 87 insertions(+) create mode 100644 client/packages/system/src/ReasonOption/Components/index.ts create mode 100644 client/packages/system/src/ReasonOption/api/api.ts create mode 100644 client/packages/system/src/ReasonOption/api/hooks/document/index.ts create mode 100644 client/packages/system/src/ReasonOption/api/hooks/document/useReasonOptions.ts create mode 100644 client/packages/system/src/ReasonOption/api/hooks/index.ts create mode 100644 client/packages/system/src/ReasonOption/api/hooks/utils/index.ts create mode 100644 client/packages/system/src/ReasonOption/api/hooks/utils/useReasonOptionsApi.ts create mode 100644 client/packages/system/src/ReasonOption/api/index.ts diff --git a/client/packages/system/src/ReasonOption/Components/index.ts b/client/packages/system/src/ReasonOption/Components/index.ts new file mode 100644 index 0000000000..8338d497c9 --- /dev/null +++ b/client/packages/system/src/ReasonOption/Components/index.ts @@ -0,0 +1 @@ +export * from './ReasonOptionsSearchInput'; diff --git a/client/packages/system/src/ReasonOption/api/api.ts b/client/packages/system/src/ReasonOption/api/api.ts new file mode 100644 index 0000000000..a18f266f28 --- /dev/null +++ b/client/packages/system/src/ReasonOption/api/api.ts @@ -0,0 +1,31 @@ +import { + SortBy, + ReasonOptionSortInput, + ReasonOptionSortFieldInput, +} from '@openmsupply-client/common'; +import { Sdk, ReasonOptionRowFragment } from './operations.generated'; + +export type ListParams = { sortBy?: SortBy }; + +const reasonOptionParsers = { + toSortInput: ( + sortBy: SortBy + ): ReasonOptionSortInput => { + return { + desc: sortBy.isDesc, + key: sortBy.key as ReasonOptionSortFieldInput, + }; + }, +}; + +export const getReasonOptionsQuery = (sdk: Sdk) => ({ + get: { + listAllActive: async ({ sortBy }: ListParams) => { + const response = await sdk.reasonOptions({ + sort: sortBy ? reasonOptionParsers.toSortInput(sortBy) : undefined, + filter: { isActive: true }, + }); + return response?.reasonOptions; + }, + }, +}); diff --git a/client/packages/system/src/ReasonOption/api/hooks/document/index.ts b/client/packages/system/src/ReasonOption/api/hooks/document/index.ts new file mode 100644 index 0000000000..aa13c2425f --- /dev/null +++ b/client/packages/system/src/ReasonOption/api/hooks/document/index.ts @@ -0,0 +1,5 @@ +import { useReasonOptions } from './useReasonOptions'; + +export const Document = { + useReasonOptions, +}; diff --git a/client/packages/system/src/ReasonOption/api/hooks/document/useReasonOptions.ts b/client/packages/system/src/ReasonOption/api/hooks/document/useReasonOptions.ts new file mode 100644 index 0000000000..de499b3cc5 --- /dev/null +++ b/client/packages/system/src/ReasonOption/api/hooks/document/useReasonOptions.ts @@ -0,0 +1,12 @@ +import { SortBy, useQuery } from '@openmsupply-client/common'; +import { ReasonOptionRowFragment } from '../../operations.generated'; +import { useReasonOptionsApi } from '../utils/useReasonOptionsApi'; + +export const useReasonOptions = (sortBy?: SortBy) => { + const api = useReasonOptionsApi(); + const result = useQuery(api.keys.sortedList(sortBy), () => + api.get.listAllActive({ sortBy }) + ); + + return { ...result }; +}; diff --git a/client/packages/system/src/ReasonOption/api/hooks/index.ts b/client/packages/system/src/ReasonOption/api/hooks/index.ts new file mode 100644 index 0000000000..084f8cf5fc --- /dev/null +++ b/client/packages/system/src/ReasonOption/api/hooks/index.ts @@ -0,0 +1,11 @@ +import { Document } from './document'; +import { Utils } from './utils'; + +export const reasonOptions = { + document: { + listAllActive: Document.useReasonOptions, + }, + utils: { + api: Utils.useReasonOptionsApi, + }, +}; diff --git a/client/packages/system/src/ReasonOption/api/hooks/utils/index.ts b/client/packages/system/src/ReasonOption/api/hooks/utils/index.ts new file mode 100644 index 0000000000..39efab994f --- /dev/null +++ b/client/packages/system/src/ReasonOption/api/hooks/utils/index.ts @@ -0,0 +1,5 @@ +import { useReasonOptionsApi } from './useReasonOptionsApi'; + +export const Utils = { + useReasonOptionsApi, +}; diff --git a/client/packages/system/src/ReasonOption/api/hooks/utils/useReasonOptionsApi.ts b/client/packages/system/src/ReasonOption/api/hooks/utils/useReasonOptionsApi.ts new file mode 100644 index 0000000000..51e3e4385b --- /dev/null +++ b/client/packages/system/src/ReasonOption/api/hooks/utils/useReasonOptionsApi.ts @@ -0,0 +1,20 @@ +import { useGql, SortBy } from '@openmsupply-client/common'; +import { getSdk, ReasonOptionRowFragment } from '../../operations.generated'; +import { getReasonOptionsQuery } from '../../api'; + +export const useReasonOptionsApi = () => { + const keys = { + base: () => ['reasonOptions'] as const, + list: () => [...keys.base(), 'list'] as const, + sortedList: (sortBy?: SortBy) => + [...keys.list(), sortBy] as const, + sortedListActive: ( + isActive: boolean, + sortBy?: SortBy + ) => [...keys.sortedList(sortBy), isActive] as const, + }; + const { client } = useGql(); + const sdk = getSdk(client); + const queries = getReasonOptionsQuery(sdk); + return { ...queries, keys }; +}; diff --git a/client/packages/system/src/ReasonOption/api/index.ts b/client/packages/system/src/ReasonOption/api/index.ts new file mode 100644 index 0000000000..7a17df81d4 --- /dev/null +++ b/client/packages/system/src/ReasonOption/api/index.ts @@ -0,0 +1,2 @@ +export * from './hooks'; +export { ReasonOptionRowFragment } from './operations.generated'; From 01e5a8f36cf12045fb6e66ae203216dca9f012b1 Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Fri, 1 Nov 2024 11:20:24 +1300 Subject: [PATCH 3/5] Component to search reason options --- .../Components/ReasonOptionsSearchInput.tsx | 91 +++++++++++++++++++ .../packages/system/src/ReasonOption/index.ts | 2 + 2 files changed, 93 insertions(+) create mode 100644 client/packages/system/src/ReasonOption/Components/ReasonOptionsSearchInput.tsx create mode 100644 client/packages/system/src/ReasonOption/index.ts diff --git a/client/packages/system/src/ReasonOption/Components/ReasonOptionsSearchInput.tsx b/client/packages/system/src/ReasonOption/Components/ReasonOptionsSearchInput.tsx new file mode 100644 index 0000000000..0b489a7cd6 --- /dev/null +++ b/client/packages/system/src/ReasonOption/Components/ReasonOptionsSearchInput.tsx @@ -0,0 +1,91 @@ +import React, { FC } from 'react'; +import { + Autocomplete, + BasicTextInput, + Box, + defaultOptionMapper, + getDefaultOptionRenderer, + ReasonOptionNode, + ReasonOptionNodeType, +} from '@openmsupply-client/common'; +import { reasonOptions } from '../api'; + +interface ReasonOptionsSearchInputProps { + value?: ReasonOptionNode | null; + width?: number | string; + onChange: (inventoryAdjustmentReason: ReasonOptionNode | null) => void; + autoFocus?: boolean; + type: ReasonOptionNodeType; + isError?: boolean; + isDisabled?: boolean; +} + +export const ReasonOptionsSearchInput: FC = ({ + value, + width, + onChange, + autoFocus = false, + type, + isError, + isDisabled, +}) => { + const { data, isLoading } = reasonOptions.document.listAllActive(); + + const reasonFilter = (reason: ReasonOptionNode) => { + switch (type) { + case ReasonOptionNodeType.PositiveInventoryAdjustment: + return reason.type === ReasonOptionNodeType.PositiveInventoryAdjustment; + case ReasonOptionNodeType.NegativeInventoryAdjustment: + return reason.type === ReasonOptionNodeType.NegativeInventoryAdjustment; + case ReasonOptionNodeType.RequisitionLineVariance: + return reason.type === ReasonOptionNodeType.RequisitionLineVariance; + case ReasonOptionNodeType.ReturnReason: + return reason.type === ReasonOptionNodeType.ReturnReason; + default: + return ReasonOptionNodeType.PositiveInventoryAdjustment; + } + }; + const reasons = (data?.nodes ?? []).filter(reasonFilter); + + const isRequired = reasons.length !== 0; + + return ( + + { + onChange(reason); + }} + renderInput={props => ( + + )} + options={defaultOptionMapper(reasons, 'reason')} + renderOption={getDefaultOptionRenderer('reason')} + isOptionEqualToValue={(option, value) => option?.id === value?.id} + /> + + ); +}; diff --git a/client/packages/system/src/ReasonOption/index.ts b/client/packages/system/src/ReasonOption/index.ts new file mode 100644 index 0000000000..e0c86fbf7b --- /dev/null +++ b/client/packages/system/src/ReasonOption/index.ts @@ -0,0 +1,2 @@ +export * from './api' +export * from './Components' \ No newline at end of file From 522b5657669a9f08118bc27c313a10235e2b272d Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Fri, 1 Nov 2024 11:25:37 +1300 Subject: [PATCH 4/5] Change prop name --- .../src/ReasonOption/Components/ReasonOptionsSearchInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/packages/system/src/ReasonOption/Components/ReasonOptionsSearchInput.tsx b/client/packages/system/src/ReasonOption/Components/ReasonOptionsSearchInput.tsx index 0b489a7cd6..bd8430a7a3 100644 --- a/client/packages/system/src/ReasonOption/Components/ReasonOptionsSearchInput.tsx +++ b/client/packages/system/src/ReasonOption/Components/ReasonOptionsSearchInput.tsx @@ -13,7 +13,7 @@ import { reasonOptions } from '../api'; interface ReasonOptionsSearchInputProps { value?: ReasonOptionNode | null; width?: number | string; - onChange: (inventoryAdjustmentReason: ReasonOptionNode | null) => void; + onChange: (reasonOption: ReasonOptionNode | null) => void; autoFocus?: boolean; type: ReasonOptionNodeType; isError?: boolean; From 27a6bfd14114d565ceef31a226322c99ad03bee0 Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Wed, 6 Nov 2024 11:23:08 +1300 Subject: [PATCH 5/5] default false --- .../src/ReasonOption/Components/ReasonOptionsSearchInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/packages/system/src/ReasonOption/Components/ReasonOptionsSearchInput.tsx b/client/packages/system/src/ReasonOption/Components/ReasonOptionsSearchInput.tsx index bd8430a7a3..1ae77f3c4b 100644 --- a/client/packages/system/src/ReasonOption/Components/ReasonOptionsSearchInput.tsx +++ b/client/packages/system/src/ReasonOption/Components/ReasonOptionsSearchInput.tsx @@ -42,7 +42,7 @@ export const ReasonOptionsSearchInput: FC = ({ case ReasonOptionNodeType.ReturnReason: return reason.type === ReasonOptionNodeType.ReturnReason; default: - return ReasonOptionNodeType.PositiveInventoryAdjustment; + return false; } }; const reasons = (data?.nodes ?? []).filter(reasonFilter);