Skip to content

Commit

Permalink
MOB-456 : integrate abacus validation error with button states (#145)
Browse files Browse the repository at this point in the history
* bump 1.6.36 -> 1.6.38

* some ui

* add label accessory to platform input, split out input views into view models

* clean up

* add cta button

* hook up button and button states

* abacus?

* clean up

* pause

* clean up

* pause

* fix keyboard, fix toggle clipping, fix trade input not scrollable

* bump 1.6.36 -> 1.6.38

* some ui

* add label accessory to platform input, split out input views into view models

* clean up

* add cta button

* hook up button and button states

* abacus?

* clean up

* pause

* clean up

* fix keyboard, fix toggle clipping, fix trade input not scrollable

* clean up

* clean up

* bump 1.6.36 -> 1.6.38

* some ui

* add label accessory to platform input, split out input views into view models

* clean up

* add cta button

* hook up button and button states

* abacus?

* clean up

* pause

* clean up

* pause

* fix keyboard, fix toggle clipping, fix trade input not scrollable

* clean up

* clean up

* add validation error handling

* use localized string extension for validation error
  • Loading branch information
mike-dydx committed Aug 20, 2024
1 parent 39f3a7f commit 864e49a
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -140,28 +140,21 @@ private class dydxTakeProfitStopLossViewPresenter: HostedViewPresenter<dydxTakeP

viewModel?.takeProfitStopLossInputAreaViewModel?.takeProfitAlert = nil
viewModel?.takeProfitStopLossInputAreaViewModel?.stopLossAlert = nil
viewModel?.customLimitPriceViewModel?.alert = nil

for error in errors {
let alert = InlineAlertViewModel(.init(title: error.resources.title?.localized, body: error.resources.text?.localized, level: .error))
switch error.code {
case "TRIGGER_MUST_ABOVE_INDEX_PRICE":
print("mmm: \(error)")
if triggerOrdersInput?.stopLossOrder?.side == .buy {
viewModel?.takeProfitStopLossInputAreaViewModel?.stopLossAlert = alert
}
if triggerOrdersInput?.takeProfitOrder?.side == .sell {
viewModel?.takeProfitStopLossInputAreaViewModel?.takeProfitAlert = alert
}
case "TRIGGER_MUST_BELOW_INDEX_PRICE":
print("mmm: \(error)")
if triggerOrdersInput?.stopLossOrder?.side == .sell {
if let error = errors.first {
if let field = error.fields?.first {
let alert = InlineAlertViewModel(.init(title: error.resources.title?.localizedString, body: error.resources.text?.localizedString, level: .error))
switch field {
case TriggerOrdersInputField.stoplossprice.rawValue, TriggerOrdersInputField.stoplossusdcdiff.rawValue, TriggerOrdersInputField.stoplosspercentdiff.rawValue:
viewModel?.takeProfitStopLossInputAreaViewModel?.stopLossAlert = alert
}
if triggerOrdersInput?.takeProfitOrder?.side == .buy {
case TriggerOrdersInputField.takeprofitprice.rawValue, TriggerOrdersInputField.takeprofitusdcdiff.rawValue, TriggerOrdersInputField.takeprofitpercentdiff.rawValue:
viewModel?.takeProfitStopLossInputAreaViewModel?.takeProfitAlert = alert
case TriggerOrdersInputField.takeprofitlimitprice.rawValue, TriggerOrdersInputField.stoplosslimitprice.rawValue:
viewModel?.customLimitPriceViewModel?.alert = alert
default:
break
}
default:
print("mmm: ", error.code)
}
}

Expand All @@ -171,6 +164,8 @@ private class dydxTakeProfitStopLossViewPresenter: HostedViewPresenter<dydxTakeP
viewModel?.takeProfitStopLossInputAreaViewModel?.stopLossPriceInputViewModel?.value = dydxFormatter.shared.raw(number: triggerOrdersInput?.stopLossOrder?.price?.triggerPrice?.doubleValue, digits: 2)
viewModel?.takeProfitStopLossInputAreaViewModel?.lossInputViewModel?.value = dydxFormatter.shared.raw(number: triggerOrdersInput?.stopLossOrder?.price?.usdcDiff?.doubleValue, digits: 2)

viewModel?.customAmountViewModel?.value = triggerOrdersInput?.size?.doubleValue.magnitude.stringValue

viewModel?.customLimitPriceViewModel?.takeProfitPriceInputViewModel?.value = triggerOrdersInput?.takeProfitOrder?.price?.limitPrice?.stringValue
viewModel?.customLimitPriceViewModel?.stopLossPriceInputViewModel?.value = triggerOrdersInput?.stopLossOrder?.price?.limitPrice?.stringValue

Expand All @@ -187,7 +182,7 @@ private class dydxTakeProfitStopLossViewPresenter: HostedViewPresenter<dydxTakeP
}

if let error = errors.first {
viewModel?.submissionReadiness = .fixErrors(cta: error.resources.action?.localized)
viewModel?.submissionReadiness = .fixErrors(cta: error.resources.action?.localizedString)
} else if triggerOrdersInput?.takeProfitOrder?.price?.triggerPrice?.doubleValue == nil
&& triggerOrdersInput?.takeProfitOrder?.orderId == nil
&& triggerOrdersInput?.stopLossOrder?.price?.triggerPrice?.doubleValue == nil
Expand Down Expand Up @@ -259,7 +254,7 @@ private class dydxTakeProfitStopLossViewPresenter: HostedViewPresenter<dydxTakeP
AbacusStateManager.shared.triggerOrders(input: order.price.stringValue, type: .stoplosslimitprice)
AbacusStateManager.shared.triggerOrders(input: order.triggerPrice?.stringValue, type: .stoplossprice)
default:
preconditionFailure("should not update from non trigger order")
assertionFailure("should not update from non trigger order")
}
}

Expand Down Expand Up @@ -304,6 +299,21 @@ private class dydxTakeProfitStopLossViewPresenter: HostedViewPresenter<dydxTakeP
AbacusStateManager.shared.triggerOrders(input: $0, type: .stoplosslimitprice)
}

// set up toggle interactions
viewModel.customAmountViewModel?.toggleAction = { _ in
// if user is turning off, also set to nil
// if user is turning on, can also set to nil
// this is an abacus limitation since a "0" value created a validation error, would be bad UX
AbacusStateManager.shared.triggerOrders(input: nil, type: .size)
}
viewModel.customLimitPriceViewModel?.toggleAction = { _ in
// if user is turning off, also set to nil
// if user is turning on, can also set to nil
// this is an abacus limitation since a "0" value created a validation error, would be bad UX
AbacusStateManager.shared.triggerOrders(input: nil, type: .takeprofitlimitprice)
AbacusStateManager.shared.triggerOrders(input: nil, type: .stoplosslimitprice)
}

// set up button interactions
viewModel.takeProfitStopLossInputAreaViewModel?.multipleOrdersExistViewModel?.viewAllAction = {
Router.shared?.navigate(to: .init(path: "/portfolio/orders"), animated: true, completion: nil)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import dydxFormatter
import Utilities

public class dydxCustomAmountViewModel: PlatformTextInputViewModel {

@Published private var isOn: Bool = false
@Published public var toggleAction: ((Bool) -> Void)?

@Published public var assetId: String? {
didSet {
guard let assetId = assetId else { return }
Expand All @@ -36,7 +40,6 @@ public class dydxCustomAmountViewModel: PlatformTextInputViewModel {
slider.maximumValue = maximumValue ?? 0
}
}
@Published private var isOn: Bool = false

public init() {
super.init(
Expand All @@ -50,7 +53,7 @@ public class dydxCustomAmountViewModel: PlatformTextInputViewModel {
PlatformBooleanInputViewModel(label: DataLocalizer.shared?.localize(path: "APP.GENERAL.CUSTOM_AMOUNT", params: nil), labelAccessory: nil, value: isOn.description, valueAccessoryView: nil) { [weak self] value in
guard let self, let value, let isOn = Bool(value) else { return }
self.isOn = isOn
self.onEdited?(isOn ? "\(minimumValue ?? 0)" : nil)
self.toggleAction?(isOn)
}
.createView()
.padding(.trailing, 2) // swiftui bug where toggle view in a scrollview gets clipped without this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ import Utilities

public class dydxCustomLimitPriceViewModel: PlatformViewModel {

@Published public var toggleAction: ((Bool) -> Void)?

@Published private var isOn: Bool = false
@Published public var takeProfitPriceInputViewModel: dydxPriceInputViewModel?
@Published public var stopLossPriceInputViewModel: dydxPriceInputViewModel?
@Published public var alert: InlineAlertViewModel?

@Published private var isTooltipPresented: Bool = false
private lazy var isTooltipPresentedBinding = Binding(
Expand All @@ -27,6 +30,7 @@ public class dydxCustomLimitPriceViewModel: PlatformViewModel {
PlatformBooleanInputViewModel(label: DataLocalizer.shared?.localize(path: "APP.TRADE.LIMIT_PRICE", params: nil), labelAccessory: nil, value: isOn.description, valueAccessoryView: nil) { [weak self] value in
guard let self, let value, let isOn = Bool(value) else { return }
self.isOn = isOn
self.toggleAction?(isOn)
}
.createView()
.padding(.trailing, 2) // swiftui bug where toggle view in a scrollview gets clipped without this
Expand All @@ -49,10 +53,13 @@ public class dydxCustomLimitPriceViewModel: PlatformViewModel {
guard let self = self else { return PlatformView.emptyView.wrappedInAnyView() }
return VStack(spacing: 15) {
self.onOffSwitch
HStack(alignment: .center, spacing: 20) {
if self.isOn {
self.takeProfitPriceInputViewModel?.createView(parentStyle: parentStyle, styleKey: styleKey)
self.stopLossPriceInputViewModel?.createView(parentStyle: parentStyle, styleKey: styleKey)
if self.isOn {
VStack(spacing: 16) {
HStack(alignment: .center, spacing: 20) {
self.takeProfitPriceInputViewModel?.createView(parentStyle: parentStyle, styleKey: styleKey)
self.stopLossPriceInputViewModel?.createView(parentStyle: parentStyle, styleKey: styleKey)
}
self.alert?.createView(parentStyle: parentStyle, styleKey: styleKey)
}
}
}
Expand Down

0 comments on commit 864e49a

Please sign in to comment.