Skip to content

Commit

Permalink
OBPIH-6118,6115 Improve preference type and add rating type option en…
Browse files Browse the repository at this point in the history
…dpoints (#4518)

* OBPIH-6118 Improve preference type options endpoint

* OBPIH-6115 Create rating type options endpoint

* OBPIH-6118 Fixes after review

* OBPIH-6115 Replace mocked rating type options and use new endpoint

* OBPIH-6115 Use api service in actions

* OBPIH-6115 Add abort controller

* OBPIH-6115 Add missing signal
  • Loading branch information
awalkowiak committed Mar 12, 2024
1 parent 95c14fc commit 64130fc
Show file tree
Hide file tree
Showing 14 changed files with 101 additions and 40 deletions.
5 changes: 5 additions & 0 deletions grails-app/controllers/org/pih/warehouse/UrlMappings.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ class UrlMappings {
action = [GET: "preferenceTypeOptions"]
}

"/api/ratingTypeCodeOptions" {
controller = { "selectOptionsApi" }
action = [GET: "ratingTypeCodeOptions"]
}

"/api/products"(parseRequest: true) {
controller = { "productApi" }
action = [GET: "list"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import grails.converters.JSON
import org.pih.warehouse.core.GlAccount
import org.pih.warehouse.core.PaymentTerm
import org.pih.warehouse.core.PreferenceType
import org.pih.warehouse.core.RatingTypeCode
import org.pih.warehouse.core.Tag
import org.pih.warehouse.core.User
import org.pih.warehouse.core.UserService
Expand Down Expand Up @@ -80,24 +81,43 @@ class SelectOptionsApiController {
}

def preferenceTypeOptions() {
List<Map<String, String>> defaultPreferenceTypes = [
[
List<Map<String, String>> preferenceTypeOptions = []

boolean includeMultiple = params.boolean("includeMultiple", false)
if (includeMultiple) {
preferenceTypeOptions.add([
id: ProductSupplierService.PREFERENCE_TYPE_MULTIPLE,
value: ProductSupplierService.PREFERENCE_TYPE_MULTIPLE,
label: g.message(code: "react.productSupplier.preferenceType.multiple.label", default: "Multiple")
],
[
])
}

boolean includeNone = params.boolean("includeNone", false)
if (includeNone) {
preferenceTypeOptions.add([
id: ProductSupplierService.PREFERENCE_TYPE_NONE,
value: ProductSupplierService.PREFERENCE_TYPE_NONE,
label: g.message(code: 'react.productSupplier.preferenceType.none.label', default: "None")
],
]
])
}

List<Map<String, String>> preferenceTypes = genericApiService.getList(PreferenceType.class.simpleName, [:]).collect {
[
id: it.id,
value: it.id,
label: it.name
]
}
defaultPreferenceTypes.addAll(preferenceTypes)

render([data: defaultPreferenceTypes] as JSON)
preferenceTypeOptions.addAll(preferenceTypes)

render([data: preferenceTypeOptions] as JSON)
}

def ratingTypeCodeOptions() {
List ratingTypeCodeOptions = RatingTypeCode.list().collect {
[id: it.name, value: it.name, label: g.message(code: "enum.RatingTypeCode.$it.name", default: it.name)]
}
render([data: ratingTypeCodeOptions] as JSON)
}
}
5 changes: 5 additions & 0 deletions grails-app/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,11 @@ enum.OrderTypeCode.PURCHASE_ORDER=Purchase Order
enum.OrderTypeCode.SALES_ORDER=Sales Order
enum.OrderTypeCode.TRANSFER_ORDER=Transfer Order
enum.OrderTypeCode.WORK_ORDER=Work Order
enum.RatingTypeCode.OUTSTANDING=Outstanding
enum.RatingTypeCode.GOOD=Good
enum.RatingTypeCode.FAIR=Fair
enum.RatingTypeCode.POOR=Poor
enum.RatingTypeCode.NOT_RATED=Not rated
enum.ReasonCode.STOCKOUT=Stock-out
enum.ReasonCode.LOW_STOCK=Low stock
enum.ReasonCode.EXPIRED=Expired product
Expand Down
9 changes: 9 additions & 0 deletions src/js/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
FETCH_PAYMENT_TERMS,
FETCH_PREFERENCE_TYPES,
FETCH_PURCHASE_ORDER_STATUSES,
FETCH_RATING_TYPE_OPTIONS,
FETCH_REASONCODES,
FETCH_REQUISITION_STATUS_CODES,
FETCH_SESSION_INFO,
Expand Down Expand Up @@ -691,3 +692,11 @@ export const fetchPreferenceTypes = (config) => async (dispatch) => {
payload: preferenceTypes?.data?.data,
});
};

export const fetchRatingTypeCodes = (config) => async (dispatch) => {
const ratingTypeCodes = await productSupplierApi.getRatingTypeOptions(config);
return dispatch({
type: FETCH_RATING_TYPE_OPTIONS,
payload: ratingTypeCodes?.data?.data,
});
};
3 changes: 3 additions & 0 deletions src/js/actions/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,6 @@ export const HIDE_INFO_BAR_MODAL = 'HIDE_INFO_BAR_MODAL';

// Product supplier
export const FETCH_PREFERENCE_TYPES = 'FETCH_PREFERENCE_TYPES';

// Rating type options
export const FETCH_RATING_TYPE_OPTIONS = 'FETCH_RATING_TYPE_OPTIONS';
2 changes: 2 additions & 0 deletions src/js/api/services/ProductSupplierApi.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import {
PREFERENCE_TYPE_OPTIONS,
PRODUCT_SUPPLIER_BY_ID,
RATING_TYPE_OPTIONS,
} from 'api/urls';
import apiClient from 'utils/apiClient';

export default {
getPreferenceTypeOptions: (config) => apiClient.get(PREFERENCE_TYPE_OPTIONS, config),
getRatingTypeOptions: (config) => apiClient.get(RATING_TYPE_OPTIONS, config),
deleteProductSupplier: (id) => apiClient.delete(PRODUCT_SUPPLIER_BY_ID(id)),
getProductSupplier: (id) => apiClient.get(PRODUCT_SUPPLIER_BY_ID(id)),
};
3 changes: 3 additions & 0 deletions src/js/api/urls.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ export const USERS_OPTIONS = `${API}/users`;
// PREFERENCE TYPES
export const PREFERENCE_TYPE_OPTIONS = `${API}/preferenceTypeOptions`;

// RATING TYPES
export const RATING_TYPE_OPTIONS = `${API}/ratingTypeCodeOptions`;

// LOCATIONS
export const LOCATION_API = `${API}/locations`;
export const LOCATION_TYPES = `${LOCATION_API}/locationTypes`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const ProductSupplierForm = () => {
control,
handleSubmit,
errors,
mockedRatingTypeCodes,
ratingTypeCodes,
onSubmit,
} = useProductSupplierForm();

Expand All @@ -30,7 +30,7 @@ const ProductSupplierForm = () => {
control,
handleSubmit,
errors,
mockedRatingTypeCodes,
ratingTypeCodes,
}}
/>
</form>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ const ProductSupplierFormMain = ({ formProps }) => {
const {
control,
errors,
mockedRatingTypeCodes,
ratingTypeCodes,
} = formProps;

return (
<div>
<DetailsSection
control={control}
errors={errors}
mockedRatingTypeCodes={mockedRatingTypeCodes}
ratingTypeCodes={ratingTypeCodes}
/>
<PreferenceTypeSection
control={control}
Expand Down Expand Up @@ -67,7 +67,7 @@ ProductSupplierFormMain.propTypes = {
}),
})),
}),
mockedRatingTypeCodes: PropTypes.shape({
ratingTypeCodes: PropTypes.shape({
id: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import Section from 'components/Layout/v2/Section';
import AdditionalDetails from 'components/productSupplier/create/subsections/AdditionalDetails';
import BasicDetails from 'components/productSupplier/create/subsections/BasicDetails';

const DetailsSection = ({ control, errors, mockedRatingTypeCodes }) => (
const DetailsSection = ({ control, errors, ratingTypeCodes }) => (
<Section title={{ label: 'react.productSupplier.form.section.details', defaultMessage: 'Details' }}>
<BasicDetails
control={control}
errors={errors}
/>
<AdditionalDetails
control={control}
mockedRatingTypeCodes={mockedRatingTypeCodes}
ratingTypeCodes={ratingTypeCodes}
errors={errors}
/>
</Section>
Expand All @@ -38,7 +38,7 @@ DetailsSection.propTypes = {
message: PropTypes.string,
}),
}).isRequired,
mockedRatingTypeCodes: PropTypes.shape({
ratingTypeCodes: PropTypes.shape({
id: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Subsection from 'components/Layout/v2/Subsection';
import RoleType from 'consts/roleType';
import { debounceOrganizationsFetch } from 'utils/option-utils';

const AdditionalDetails = ({ control, mockedRatingTypeCodes, errors }) => {
const AdditionalDetails = ({ control, ratingTypeCodes, errors }) => {
const {
debounceTime,
minSearchLength,
Expand Down Expand Up @@ -54,7 +54,7 @@ const AdditionalDetails = ({ control, mockedRatingTypeCodes, errors }) => {
id: 'react.productSupplier.form.ratingTypeCode.tooltip',
defaultMessage: 'Product quality rating based on user feedback or sample review',
}}
options={mockedRatingTypeCodes}
options={ratingTypeCodes}
errorMessage={errors.ratingTypeCode?.message}
{...field}
/>
Expand Down Expand Up @@ -95,7 +95,7 @@ export default AdditionalDetails;

AdditionalDetails.propTypes = {
control: PropTypes.shape({}).isRequired,
mockedRatingTypeCodes: PropTypes.shape({
ratingTypeCodes: PropTypes.shape({
id: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ const useProductSupplierFilters = (ignoreClearFilters) => {
const controller = new AbortController();
const config = {
signal: controller.signal,
params: {
includeMultiple: true,
includeNone: true,
},
};
dispatch(fetchPreferenceTypes(config));

Expand Down
44 changes: 24 additions & 20 deletions src/js/hooks/productSupplier/form/useProductSupplierForm.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { useEffect } from 'react';

import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { useDispatch, useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';

import { fetchRatingTypeCodes } from 'actions';
import productSupplierApi from 'api/services/ProductSupplierApi';
import useProductSupplierValidation from 'hooks/productSupplier/form/useProductSupplierValidation';
import { omitEmptyValues } from 'utils/form-values-utils';
Expand All @@ -11,6 +15,25 @@ const useProductSupplierForm = () => {
const { validationSchema } = useProductSupplierValidation();
// Check if productSupplierId is provided in the URL (determine whether it is create or edit)
const { productSupplierId } = useParams();
const dispatch = useDispatch();

const {
ratingTypeCodes,
} = useSelector((state) => ({
ratingTypeCodes: state.productSupplier.ratingTypeCodes,
}));

useEffect(() => {
const controller = new AbortController();
const config = {
signal: controller.signal,
};
dispatch(fetchRatingTypeCodes(config));

return () => {
controller.abort();
};
}, []);

// Fetches product supplier to edit and returns default values that should be set
const getProductSupplier = async () => {
Expand Down Expand Up @@ -75,25 +98,6 @@ const useProductSupplierForm = () => {
resolver: zodResolver(validationSchema),
});

// TODO: To be replaced by rating type codes returned from the API
const mockedRatingTypeCodes = [
{
id: 'OUTSTANDING',
value: 'OUTSTANDING',
label: 'OUTSTANDING',
},
{
id: 'GOOD',
value: 'GOOD',
label: 'GOOD',
},
{
id: 'FAIR',
value: 'FAIR',
label: 'FAIR',
},
];

const onSubmit = (values) => {
const payload = {
...omitEmptyValues(values),
Expand All @@ -116,7 +120,7 @@ const useProductSupplierForm = () => {
handleSubmit,
errors,
isValid,
mockedRatingTypeCodes,
ratingTypeCodes,
onSubmit,
};
};
Expand Down
8 changes: 7 additions & 1 deletion src/js/reducers/productSupplierReducer.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { FETCH_PREFERENCE_TYPES } from 'actions/types';
import { FETCH_PREFERENCE_TYPES, FETCH_RATING_TYPE_OPTIONS } from 'actions/types';

const initialState = {
preferenceTypes: [],
ratingTypeCodes: [],
};

export default function productSupplierReducer(state = initialState, action) {
Expand All @@ -11,6 +12,11 @@ export default function productSupplierReducer(state = initialState, action) {
...state,
preferenceTypes: action.payload,
};
case FETCH_RATING_TYPE_OPTIONS:
return {
...state,
ratingTypeCodes: action.payload,
};
default:
return state;
}
Expand Down

0 comments on commit 64130fc

Please sign in to comment.