Skip to content

Commit

Permalink
feat: Payment Operations Amount Filter (#1796)
Browse files Browse the repository at this point in the history
  • Loading branch information
kanikabansal-juspay authored Nov 29, 2024
1 parent e2789d9 commit 8102096
Show file tree
Hide file tree
Showing 13 changed files with 294 additions and 18 deletions.
2 changes: 1 addition & 1 deletion public/hyperswitch/icons/solid.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion src/components/Filter.res
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,11 @@ let make = (
</div>}
</Menu>

<Form onSubmit initialValues=initialValueJson>
<Form
onSubmit
initialValues=initialValueJson
validate={values =>
values->OrderUIUtils.validateForm(~fieldsToValidate=[StartAmount, EndAmount])}>
<AutoSubmitter autoApply submit=onSubmit defaultFilterKeys submitInputOnEnter />
{<AddDataAttributes attributes=[("data-filter", "remoteFilters")]>
{<>
Expand Down
6 changes: 3 additions & 3 deletions src/components/FilterSelectBox.res
Original file line number Diff line number Diff line change
Expand Up @@ -1882,7 +1882,7 @@ module BaseDropdown = {
onClick
className={`${textStyle->Option.getOr(
"",
)} flex justify-center items-center whitespace-pre leading-5 text-sm font-medium hover:bg-opacity-80 cursor-pointer mr-2 border-r-2 pr-1`}>
)} flex justify-center items-center whitespace-pre leading-5 text-sm font-medium hover:bg-opacity-80 cursor-pointer mr-2 pr-1`}>
<div className="text-ellipsis overflow-hidden w-full max-w-sm h-fit">
{selectButtonText->React.string}
</div>
Expand All @@ -1898,7 +1898,7 @@ module BaseDropdown = {
<div
className={`flex ${customButtonStyle} ${showDropDown
? buttonStyleOnDropDownOpened
: ""} transition duration-[250ms] ease-out-[cubic-bezier(0.33, 1, 0.68, 1)] border`}>
: ""} transition duration-[250ms] ease-out-[cubic-bezier(0.33, 1, 0.68, 1)] justify-between border`}>
{if (
showToolTip &&
newInputSelect.value !== ""->JSON.Encode.string &&
Expand All @@ -1919,7 +1919,7 @@ module BaseDropdown = {
selectButton
}}
<div
className="p-1 rounded-lg hover:bg-gray-200 cursor-pointer "
className="p-1 hover:bg-gray-200 cursor-pointer border-l-2 pl-2.5 "
onClick={_ => newInputSelect.name->onDeleteClick}>
<Icon size={13} name="cross-outline" />
</div>
Expand Down
30 changes: 19 additions & 11 deletions src/components/RemoteFiltersUtils.res
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ let getStrFromJson = (key, val) => {
switch val->JSON.Classify.classify {
| String(str) => str
| Array(array) => array->Array.length > 0 ? `[${array->Array.joinWithUnsafe(",")}]` : ""
| Number(num) => key === "offset" ? "0" : num->Float.toInt->Int.toString
| Number(num) => key === "offset" ? "0" : num->Float.toString
| _ => ""
}
}
Expand Down Expand Up @@ -188,16 +188,24 @@ let getInitialValuesFromUrl = (
})
entriesList->Array.forEach(entry => {
let (key, value) = entry
initialFilters->Array.forEach((filter: FormRenderer.fieldInfoType) => {
filter.inputNames->Array.forEach(
name => {
if name === key {
Dict.set(dict, key, value->UrlFetchUtils.getFilterValue)
}
},
)
})

let isAmountKey = switch key {
| "start_amount"
| "end_amount" => true
| _ => false
}
if isAmountKey {
Dict.set(dict, key, value->UrlFetchUtils.getFilterValue)
} else {
initialFilters->Array.forEach((filter: FormRenderer.fieldInfoType) => {
filter.inputNames->Array.forEach(
name => {
if name === key {
Dict.set(dict, key, value->UrlFetchUtils.getFilterValue)
}
},
)
})
}
options->Array.forEach(option => {
let fieldName = option.urlKey
if fieldName === key {
Expand Down
2 changes: 1 addition & 1 deletion src/components/form/FormRenderer.res
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ module SubmitButton = {
~tooltipPositioning: ToolTip.tooltipPositioning=#fixed,
~withDialog=false,
~modalObj: option<modalObj>=?,
~tooltipWidthClass="w-64",
~tooltipWidthClass="w-auto",
~tooltipForWidthClass="",
~tooltipForHeight="h-full",
~userInteractionRequired=false,
Expand Down
5 changes: 5 additions & 0 deletions src/context/FilterContext.res
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ let make = (~index: string, ~children) => {
setfilterDict(prev => {
let updatedDict =
prev->Dict.toArray->Array.copy->Dict.fromArray->DictionaryUtils.deleteKeys(arr)
let updatedDict = if arr == ["amount"] {
updatedDict->DictionaryUtils.deleteKeys(["start_amount", "end_amount"])
} else {
updatedDict
}
let dict = if DictionaryUtils.equalDicts(updatedDict, prev) {
prev
} else {
Expand Down
76 changes: 76 additions & 0 deletions src/entryPoints/AuthModule/Common/CommonInputFields.res
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,79 @@ let passwordField = FormRenderer.makeFieldInfo(
),
~isRequired=false,
)

let startamountField = FormRenderer.makeFieldInfo(
~label="",
~name="start_amount",
~placeholder="0",
~customInput=InputFields.numericTextInput(),
~type_="number",
)

let endAmountField = FormRenderer.makeFieldInfo(
~label="",
~name="end_amount",
~placeholder="0",
~customInput=InputFields.numericTextInput(),
~type_="number",
)

module CustomAmountEqualField = {
@react.component
let make = () => {
let form = ReactFinalForm.useForm()
<div className={"flex gap-5 items-center justify-center w-28 ml-2"}>
<FormRenderer.FieldRenderer
labelClass="font-semibold !text-black"
field={FormRenderer.makeFieldInfo(~label="", ~name="start_amount", ~customInput=(
~input,
~placeholder as _,
) =>
InputFields.numericTextInput()(
~input={
...input,
onChange: {
ev => {
form.change("end_amount", ev->Identity.genericTypeToJson)
input.onChange(ev)
}
},
},
~placeholder="0",
)
)}
/>
</div>
}
}

module CustomAmountBetweenField = {
@react.component
let make = () => {
let form = ReactFinalForm.useForm()
<div className="flex gap-1 items-center justify-center mx-1 w-10.25-rem">
<FormRenderer.FieldRenderer
labelClass="font-semibold !text-black"
field={FormRenderer.makeFieldInfo(~label="", ~name="start_amount", ~customInput=(
~input,
~placeholder as _,
) =>
InputFields.numericTextInput()(
~input={
...input,
onChange: {
ev => {
form.change("end_amount", 0->Identity.genericTypeToJson)
input.onChange(ev)
}
},
},
~placeholder="0",
)
)}
/>
<p className="mt-3 text-xs text-jp-gray-700"> {"and"->React.string} </p>
<FormRenderer.FieldRenderer labelClass="font-semibold !text-black" field=endAmountField />
</div>
}
}
39 changes: 39 additions & 0 deletions src/screens/Order/OrderTypes.res
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,47 @@ type optionObj = {

type frmStatus = [#APPROVE | #REJECT]

type amountFilter =
| GreaterThanEqualTo
| LessThanEqualTo
| EqualTo
| InBetween
| UnknownRange(string)

type amountFields =
| StartAmount
| EndAmount
| UnknownValidateFields(string)

let validationFieldsMapper = key => {
switch key {
| StartAmount => "start_amount"
| EndAmount => "end_amount"
| UnknownValidateFields(key) => key
}
}

let getSortString = (value: LoadedTable.sortOb) =>
switch value.sortType {
| ASC => "asc"
| DSC => "desc"
}

let mapStringToRange = val =>
switch val {
| "Greater than Equal to" => GreaterThanEqualTo
| "Less than Equal to" => LessThanEqualTo
| "Equal to" => EqualTo
| "In Between" => InBetween
| _ => UnknownRange(val)
}

let mapRangeTypetoString = amountFilter => {
switch amountFilter {
| GreaterThanEqualTo => "Greater than Equal to"
| LessThanEqualTo => "Less than Equal to"
| EqualTo => "Equal to"
| InBetween => "In Between"
| UnknownRange(string) => string
}
}
46 changes: 46 additions & 0 deletions src/screens/Order/OrderUIUtils.res
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
open OrderTypes
type filterTypes = {
connector: array<string>,
currency: array<string>,
Expand All @@ -8,6 +9,7 @@ type filterTypes = {
connector_label: array<string>,
card_network: array<string>,
customer_id: array<string>,
amount: array<string>,
}

type filter = [
Expand All @@ -20,6 +22,7 @@ type filter = [
| #connector_label
| #card_network
| #customer_id
| #amount
| #unknown
]

Expand All @@ -34,6 +37,7 @@ let getFilterTypeFromString = filterType => {
| "connector_label" => #connector_label
| "card_network" => #card_network
| "customer_id" => #customer_id
| "amount" => #amount
| _ => #unknown
}
}
Expand Down Expand Up @@ -270,6 +274,7 @@ let itemToObjMapper = dict => {
connector_label: [],
card_network: dict->getArrayFromDict("card_network", [])->getStrArrayFromJsonArray,
customer_id: [],
amount: [],
}
}

Expand All @@ -290,6 +295,7 @@ let initialFilters = (json, filtervalues, removeKeys, filterKeys, setfilterKeys)
}
arr->Array.push("payment_method_type")
arr->Array.push("customer_id")
arr->Array.push("amount")
arr->Array.map((key): EntityType.initialFilters<'t> => {
let values = switch key->getFilterTypeFromString {
| #connector => filterArr.connector
Expand All @@ -316,6 +322,19 @@ let initialFilters = (json, filtervalues, removeKeys, filterKeys, setfilterKeys)
})
}

let amountFilterOptions: array<FilterSelectBox.dropdownOption> = [
GreaterThanEqualTo,
LessThanEqualTo,
EqualTo,
InBetween,
]->Array.map(option => {
let label = option->mapRangeTypetoString
{
FilterSelectBox.label,
value: label,
}
})

let options = switch key->getFilterTypeFromString {
| #connector_label => getOptionsForOrderFilters(filterDict, filtervalues)
| _ => values->makeOptions
Expand All @@ -335,6 +354,10 @@ let initialFilters = (json, filtervalues, removeKeys, filterKeys, setfilterKeys)
<Icon name="cross-outline" size=13 />
</div>,
)(~input, ~placeholder=`Enter ${input.name->snakeToTitle}...`)
| #amount =>
(~input as _, ~placeholder as _) => {
<OrdersHelper options=amountFilterOptions />
}

| _ =>
InputFields.filterMultiSelectInput(
Expand Down Expand Up @@ -512,3 +535,26 @@ let orderViewList: OMPSwitchTypes.ompViews = [
entity: #Profile,
},
]

let deleteNestedKeys = (dict: Dict.t<'a>, keys: array<string>) => {
keys->Array.forEach(key => dict->Dict.delete(key))
}

let validateForm = (values, ~fieldsToValidate: array<amountFields>) => {
let errors = Dict.make()
open LogicUtils
let valuesDict = values->JsonFlattenUtils.flattenObject(false)
let amountValues = fieldsToValidate->Array.map(key => {
valuesDict->getJsonObjectFromDict(key->validationFieldsMapper)
})
let start_amount = amountValues->getValueFromArray(0, JSON.Encode.null)
let end_amount = amountValues->getValueFromArray(1, JSON.Encode.null)
if start_amount->isNullJson && end_amount->isNullJson {
errors->Dict.set("Invalid", "Please enter value."->JSON.Encode.string)
} else if !isNullJson(start_amount) && !isNullJson(end_amount) {
if end_amount < start_amount {
errors->Dict.set("Invalid", "Please enter valid range."->JSON.Encode.string)
}
}
errors->JSON.Encode.object
}
23 changes: 22 additions & 1 deletion src/screens/Order/Orders.res
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,34 @@ let make = (~previewOnly=false) => {
]->getJsonFromArrayOfJson,
)
}

let encodeFloatOrDefault = val => (val->getFloatFromJson(0.0) *. 100.0)->JSON.Encode.float
filters->Dict.set(
"amount_filter",
[
(
"start_amount",
getvalFromDict(dict, "start_amount")->mapOptionOrDefault(
JSON.Encode.null,
encodeFloatOrDefault,
),
),
(
"end_amount",
getvalFromDict(dict, "end_amount")->mapOptionOrDefault(
JSON.Encode.null,
encodeFloatOrDefault,
),
),
]->getJsonFromArrayOfJson,
)
dict
->Dict.toArray
->Array.forEach(item => {
let (key, value) = item
filters->Dict.set(key, value)
})
filters->OrderUIUtils.deleteNestedKeys(["start_amount", "end_amount"])

filters
->getOrdersList(
~updateDetails,
Expand Down
Loading

0 comments on commit 8102096

Please sign in to comment.