Implement billing modal.
[?]
Feb 5, 2021, 6:48 AM
YBLHJFCNW52TJ37UIHPZ6UD22SQVGG27SP5UQR7YAIJ7F7SYJZSACDependencies
- [2]
3HTCTHHUAdd halogen-portal dependency and update argonaut. - [3]
N6FG4EW6Working bootstrap modal! Only a little FFI. - [4]
VTZT2ILUWire up billing navigation. - [5]
SAESJLLYInitial experiments in hash routing. - [6]
ANDJ6GEYAdd billing component skeleton. - [7]
U7YAT2ZKAdd error reporting to signup form. - [8]
QH4UB73NFormat with purty. - [9]
PT4276XCAdd logout functionality. - [10]
T2DN23M7Factor out billing create component. - [11]
GLQSD33YUse mock capability for overview init. - [12]
27H4DECZAdd billing create API call. - [13]
4GOBY5NQWIP on modals. - [14]
AAALU5A2Fix client routing - [*]
NJNMO72SAdd zcash.com submodule and update client to modern halogen. - [*]
RB2ETNIFAdd skeletal PureScript client project.
Change contents
- edit in client/spago.dhall at line 15
, "numbers" - replacement in client/src/Aftok/Api/Billing.purs at line 9
import Data.Argonaut.Decode (class DecodeJson, decodeJson, JsonDecodeError(..))import Data.Argonaut.Decode (class DecodeJson, decodeJson, JsonDecodeError(..), (.:)) - edit in client/src/Aftok/Api/Billing.purs at line 14
import Data.Interval.Duration (Duration) - replacement in client/src/Aftok/Api/Billing.purs at line 21
import Data.Time.Duration (Hours(..), Days(..))import Data.Time.Duration (Hours) - replacement in client/src/Aftok/Api/Billing.purs at line 57
uuidStr <- decodeJson jsonobj <- decodeJson jsonuuidStr <- obj .: "billableId" - replacement in client/src/Aftok/Api/Billing.purs at line 86
{ name: b.name{ schemaVersion: "1.0", name: b.name - edit in client/src/Aftok/Api/Billing.purs at line 93
, gracePeriod: unwrap b.gracePeriod, requestExpiryPeriod: unwrap b.expiryPeriod - replacement in client/src/Aftok/Billing/Create.purs at line 6
import Data.Either (Either(..))import Data.Foldable (all)import Data.Maybe (Maybe(..))import Data.Either (Either(..), note)import Data.Fixed as Fixedimport Data.Foldable (any)import Data.Int as Intimport Data.Maybe (Maybe(..), maybe)import Data.Newtype (unwrap)import Data.Number (fromString) as Numberimport Data.Number.Format (toString) as Number - edit in client/src/Aftok/Billing/Create.purs at line 15
import Data.Validation.Semigroup (V(..), toEither) - replacement in client/src/Aftok/Billing/Create.purs at line 17
import Data.Traversable (traverse)import Data.Tuple (Tuple)-- import Data.Traversable (traverse)import Data.Tuple (Tuple(..)) - edit in client/src/Aftok/Billing/Create.purs at line 27
import Aftok.ProjectList as ProjectList - replacement in client/src/Aftok/Billing/Create.purs at line 28
import Aftok.Api.Types (APIError(..))import Aftok.Api.Project (Project)import Aftok.HTML.Classes as C - edit in client/src/Aftok/Billing/Create.purs at line 31
import Aftok.Api.Types (APIError(..)) - replacement in client/src/Aftok/Billing/Create.purs at line 35
, PaymentRequestId, PaymentRequest, Recurrence(..) - edit in client/src/Aftok/Billing/Create.purs at line 37
, listProjectBillables, listUnpaidPaymentRequests - edit in client/src/Aftok/Billing/Create.purs at line 38
import Aftok.Zcash (ZEC(..), toZatoshi)data Field= NameField| DescField| MessageField| MonthlyRecurrenceField| WeeklyRecurrenceField| AmountField| GracePeriodField| RequestExpiryField - edit in client/src/Aftok/Billing/Create.purs at line 50
derive instance fieldEq :: Eq Fieldderive instance fieldOrd :: Ord Field - edit in client/src/Aftok/Billing/Create.purs at line 59
derive instance rtypeEq :: Eq RType - replacement in client/src/Aftok/Billing/Create.purs at line 66
, recurrenceType :: Maybe RType, recurrenceType :: RType - replacement in client/src/Aftok/Billing/Create.purs at line 68
, amount :: Maybe Number, amount :: Maybe ZEC - edit in client/src/Aftok/Billing/Create.purs at line 71
, fieldErrors :: Array Field - replacement in client/src/Aftok/Billing/Create.purs at line 87
| SetRecurrenceDuration Number| SetBillingAmount Number| SetRecurrenceMonths String| SetRecurrenceWeeks String| SetBillingAmount String| SetGracePeriod String| SetRequestExpiry String - replacement in client/src/Aftok/Billing/Create.purs at line 125
, recurrenceType : Nothing, recurrenceType : RTOneTime - edit in client/src/Aftok/Billing/Create.purs at line 130
, fieldErrors : [] - replacement in client/src/Aftok/Billing/Create.purs at line 135
Modals.modal "createBillable" "Create Billable" SaveBillableModals.modalWithSave "createBillable" "Create Billable" SaveBillable - replacement in client/src/Aftok/Billing/Create.purs at line 137
[ HH.div[ P.classes (ClassName <$> ["form-group"]) ][ formGroup st[ NameField ] - replacement in client/src/Aftok/Billing/Create.purs at line 140
[ P.for "billableName", P.classes (ClassName <$> ["font-weight-bold", "mb-1"] )][ HH.text "Bill Name:" ][ P.for "billableName"][ HH.text "Product Name" ] - replacement in client/src/Aftok/Billing/Create.purs at line 144
, P.classes (ClassName <$> [ "form-control-sm" ]), P.classes [ C.formControlSm ] - edit in client/src/Aftok/Billing/Create.purs at line 147
, P.required true, P.autofocus true - replacement in client/src/Aftok/Billing/Create.purs at line 149
, HH.label[ P.for "billableDesc", P.classes (ClassName <$> ["font-weight-bold", "mb-1"] )][ HH.text "Bill Description:" ]], formGroup st[ DescField ][ HH.label[ P.for "billableDesc"][ HH.text "Product Description" ] - replacement in client/src/Aftok/Billing/Create.purs at line 157
, P.classes (ClassName <$> [ "form-control-sm" ]), P.classes [ C.formControlSm ] - edit in client/src/Aftok/Billing/Create.purs at line 160
, P.required true, P.autofocus true - replacement in client/src/Aftok/Billing/Create.purs at line 162
, HH.label[ P.for "billableMsg", P.classes (ClassName <$> ["font-weight-bold", "mb-1"] )][ HH.text "Message to be included with bill:" ]], formGroup st[ MessageField ][ HH.label[ P.for "billableMsg"][ HH.text "Message to be included with bill" ] - edit in client/src/Aftok/Billing/Create.purs at line 170
, P.classes (ClassName <$> [ "form-control-sm" ]) - replacement in client/src/Aftok/Billing/Create.purs at line 171
, P.placeholder "Description of the product or service", P.required true, P.autofocus true, E.onValueInput (Just <<< SetDesc), P.placeholder "Enter your message here", E.onValueInput (Just <<< SetMessage)]], formGroup st[MonthlyRecurrenceField, WeeklyRecurrenceField][ HH.label_[ HH.input([ P.type_ P.InputRadio, P.name "recurType", E.onClick \_ -> Just (SetRecurrenceType RTAnnual)] <> (if st.recurrenceType == RTAnnual then [P.checked true] else [])), HH.text " Annual"], HH.label_[ HH.input([ P.type_ P.InputRadio, P.name "recurType", E.onClick \_ -> Just (SetRecurrenceType RTMonthly)] <> (if st.recurrenceType == RTMonthly then [P.checked true] else [])), HH.text " every ", HH.input[ P.type_ P.InputNumber, P.classes [ C.formControlSm ], P.value (if st.recurrenceType == RTMonthlythen maybe "" show st.recurrenceValueelse ""), P.min 1.0, P.max 12.0, E.onValueInput (Just <<< SetRecurrenceMonths)], HH.text " Months"], HH.label_[ HH.input([ P.type_ P.InputRadio, P.name "recurType", E.onClick \_ -> Just (SetRecurrenceType RTWeekly)] <> (if st.recurrenceType == RTWeekly then [P.checked true] else [])), HH.text " every ", HH.input[ P.type_ P.InputNumber, P.classes [ C.formControlSm ], P.value (if st.recurrenceType == RTWeeklythen maybe "" show st.recurrenceValueelse ""), P.min 1.0, P.max 12.0, E.onValueInput (Just <<< SetRecurrenceWeeks)], HH.text " Weeks"], HH.label_[ HH.input([ P.type_ P.InputRadio, P.name "recurType", E.onClick \_ -> Just (SetRecurrenceType RTOneTime)] <> (if st.recurrenceType == RTOneTime then [P.checked true] else [])), HH.text " One-Time"]], formGroup st[AmountField][ HH.label[ P.for "billableAmount"][ HH.text "Amount" ], HH.input[ P.type_ P.InputNumber, P.classes [ C.formControlSm ], P.id_ "billableAmount", P.value (maybe "" (Fixed.toString <<< unwrap) st.amount), P.placeholder "1.0", P.min 0.0, E.onValueInput (Just <<< SetBillingAmount) - edit in client/src/Aftok/Billing/Create.purs at line 246
, HH.div[ P.classes [ ClassName "input-group-append" ] ][ HH.span [ P.classes [ ClassName "input-group-text" ] ] [ HH.text "ZEC" ] ] - edit in client/src/Aftok/Billing/Create.purs at line 250
, formGroup st[GracePeriodField][ HH.label[ P.for "gracePeriod"][ HH.text "Grace Period (Hours)" ], HH.input[ P.type_ P.InputNumber, P.id_ "gracePeriod", P.classes [ C.formControlSm ], P.value (maybe "" (Number.toString <<< unwrap) st.gracePeriod), P.placeholder "Hours until a bill is considered overdue", P.min 0.0, E.onValueInput (Just <<< SetGracePeriod)]], formGroup st[RequestExpiryField][ HH.label[ P.for "requestExpiry"][ HH.text "Request Expiry Period (Hours)" ], HH.input[ P.type_ P.InputNumber, P.id_ "gracePeriod", P.classes [ C.formControlSm ], P.value (maybe "" (Number.toString <<< unwrap) st.requestExpiry), P.placeholder "Hours until a payment request expires", P.min 0.0, E.onValueInput (Just <<< SetRequestExpiry)]] - replacement in client/src/Aftok/Billing/Create.purs at line 283
colmd :: forall a s. Int -> Array (H.ComponentHTML a s m) -> H.ComponentHTML a s mcolmd i xs = HH.div [ P.classes (ClassName <$> [ "col-md-" <> show i ]) ] xsformGroup :: forall i a. CState -> Array Field -> Array (HH.HTML i a) -> HH.HTML i aformGroup st fields body =HH.div[ P.classes [C.formGroup] ](body <> (fieldError st =<< fields)) - edit in client/src/Aftok/Billing/Create.purs at line 289
fieldError :: forall i a. CState -> Field -> Array (HH.HTML i a)fieldError st field =if any (_ == field) st.fieldErrorsthen case field ofNameField -> err "The name field is required"DescField -> err "The description field is required"MessageField -> err "The message field is required"MonthlyRecurrenceField -> err "You must enter a valid number of months."WeeklyRecurrenceField -> err "You must enter a valid number of weeks."AmountField -> err "You must enter a valid amount of ZEC"GracePeriodField -> err "You must enter a valid number of hours."RequestExpiryField -> err "You must enter a valid number of hours."else []whereerr str = [ HH.div_ [ HH.span [ P.classes (ClassName <$> [ "badge", "badge-danger-soft" ]) ] [ HH.text str ] ] ] - replacement in client/src/Aftok/Billing/Create.purs at line 309
SetName name -> pure unitSetDesc desc -> pure unitSetMessage msg -> pure unitSetRecurrenceType rtype -> pure unitSetRecurrenceDuration dur -> pure unitSetBillingAmount amt -> pure unitSaveBillable ->lift $ system.toggleModal "createBillable" ModalFFI.HideModalSetName name ->H.modify_ (_ { name = Just name })SetDesc desc ->H.modify_ (_ { description = Just desc })SetMessage msg ->H.modify_ (_ { message = Just msg })SetRecurrenceType rtype -> docurRecurType <- H.gets _.recurrenceTypecurDuration <- H.gets _.recurrenceValuelet rdur = case curRecurType ofRTMonthly | rtype == RTMonthly -> curDurationRTWeekly | rtype == RTWeekly -> curDuration_ -> NothingH.modify_ (_ { recurrenceType = rtype, recurrenceValue = rdur })SetRecurrenceMonths dur ->case Int.fromString dur of(Just n) -> H.modify_ (_ { recurrenceType = RTMonthly, recurrenceValue = Just n })(Nothing) -> pure unitSetRecurrenceWeeks dur ->case Int.fromString dur of(Just n) -> H.modify_ (_ { recurrenceType = RTWeekly, recurrenceValue = Just n })(Nothing) -> pure unitSetBillingAmount amt ->case Fixed.fromString amt of(Just zec) -> H.modify_ (_ { amount = Just (ZEC zec) })(Nothing) -> pure unitSetGracePeriod dur ->case Number.fromString dur of(Just n) -> H.modify_ (_ { gracePeriod = Just (Hours n) })(Nothing) -> pure unitSetRequestExpiry dur ->case Number.fromString dur of(Just n) -> H.modify_ (_ { requestExpiry = Just (Hours n) })(Nothing) -> pure unitSaveBillable -> donameV <- V <<< note [NameField] <$> H.gets (_.name)descV <- V <<< note [DescField] <$> H.gets (_.description)msgV <- V <<< note [MessageField] <$> H.gets (_.message)rtype <- H.gets (_.recurrenceType)rvalueV <- case rtype ofRTAnnual -> pure $ V (Right Annually)RTMonthly -> V <<< maybe (Left [MonthlyRecurrenceField]) (Right <<< Monthly) <$> H.gets (_.recurrenceValue)RTWeekly -> V <<< maybe (Left [WeeklyRecurrenceField]) (Right <<< Weekly) <$> H.gets (_.recurrenceValue)RTOneTime -> pure $ V (Right OneTime)zatsV <- V <<< maybe (Left [AmountField]) (Right <<< toZatoshi) <$> H.gets (_.amount)gperV <- V <<< note [GracePeriodField] <$> H.gets (_.gracePeriod)expiryV <- V <<< note [RequestExpiryField] <$> H.gets (_.requestExpiry)let toBillable = { name: _, description: _, message: _, recurrence: _, amount: _, gracePeriod: _, expiryPeriod: _}reqV :: V (Array Field) BillablereqV =toBillable <$> nameV<*> descV<*> msgV<*> rvalueV<*> zatsV<*> gperV<*> expiryVcase toEither reqV ofLeft errors -> doH.modify_ (_ { fieldErrors = errors })Right billable -> dolift $ system.log "BILLABLE OK"pid <- H.gets (_.projectId)res <- lift $ caps.createBillable pid billablecase res ofRight bid -> doH.raise (Tuple bid billable)lift $ system.toggleModal "createBillable" ModalFFI.HideModalLeft errs ->lift $ system.error (show errs)apiCapability :: Capability AffapiCapability ={ createBillable: createBillable} - edit in client/src/Aftok/Billing/Create.purs at line 394
mockCapability :: Capability AffmockCapability ={ createBillable: \_ _ -> pure $ Left Forbidden } - file addition: PaymentRequest.purs[4.454]
module Aftok.Billing.PaymentRequest where{--<div role="document" class="ant-modal" style="width: 520px; transform-origin: 724px 147.062px;"><div tabindex="0" style="width: 0px; height: 0px; overflow: hidden;">sentinelStart</div><div class="ant-modal-content"><button aria-label="Close" class="ant-modal-close"><span class="ant-modal-close-x"><i aria-label="icon: close" class="anticon anticon-close ant-modal-close-icon"><svg viewBox="64 64 896 896" class="" data-icon="close" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 0 0 203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path></svg></i></span></button><div class="ant-modal-header"><div class="ant-modal-title" id="rcDialogTitle0">Tip a proposal</div></div><div class="ant-modal-body"><div class="TipJarModal"><div class="TipJarModal-uri"><div><div class="TipJarModal-uri-qr"><span style="opacity: 1;"><canvas height="128" width="128" style="height: 128px; width: 128px;"></canvas></span></div></div><div class="TipJarModal-uri-info"><div class="ant-row ant-form-item TipJarModal-uri-info-input CopyInput"><div class="ant-form-item-label"><label class="" title="Amount">Amount</label></div><div class="ant-form-item-control-wrapper"><div class="ant-form-item-control"><span class="ant-form-item-children"><span class="ant-input-group-wrapper"><span class="ant-input-wrapper ant-input-group"><input type="number" placeholder="Amount to send" class="ant-input" value="0.2"><span class="ant-input-group-addon">ZEC</span></span></span></span></div></div></div><div class="ant-row ant-form-item CopyInput TipJarModal-uri-info-input is-textarea"><div class="ant-form-item-label"><label class="" title="Payment URI">Payment URI</label></div><div class="ant-form-item-control-wrapper"><div class="ant-form-item-control"><span class="ant-form-item-children"><textarea readonly="" rows="3" class="ant-input">zcash:zs1xzymv205x8hhn8kt3pu43c6knjlelvxfgzgsyyus9yxhmdvqeu0yj0m2knzd3p93slsygkp94rz?amount=0.2</textarea><button type="button" class="ant-btn ant-btn-icon-only"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></span></div></div></div><a href="zcash:zs1xzymv205x8hhn8kt3pu43c6knjlelvxfgzgsyyus9yxhmdvqeu0yj0m2knzd3p93slsygkp94rz?amount=0.2" class="ant-btn ant-btn-ghost ant-btn-lg ant-btn-block"><span>Open in Wallet </span><i aria-label="icon: link" class="anticon anticon-link"><svg viewBox="64 64 896 896" class="" data-icon="link" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M574 665.4a8.03 8.03 0 0 0-11.3 0L446.5 781.6c-53.8 53.8-144.6 59.5-204 0-59.5-59.5-53.8-150.2 0-204l116.2-116.2c3.1-3.1 3.1-8.2 0-11.3l-39.8-39.8a8.03 8.03 0 0 0-11.3 0L191.4 526.5c-84.6 84.6-84.6 221.5 0 306s221.5 84.6 306 0l116.2-116.2c3.1-3.1 3.1-8.2 0-11.3L574 665.4zm258.6-474c-84.6-84.6-221.5-84.6-306 0L410.3 307.6a8.03 8.03 0 0 0 0 11.3l39.7 39.7c3.1 3.1 8.2 3.1 11.3 0l116.2-116.2c53.8-53.8 144.6-59.5 204 0 59.5 59.5 53.8 150.2 0 204L665.3 562.6a8.03 8.03 0 0 0 0 11.3l39.8 39.8c3.1 3.1 8.2 3.1 11.3 0l116.2-116.2c84.5-84.6 84.5-221.5 0-306.1zM610.1 372.3a8.03 8.03 0 0 0-11.3 0L372.3 598.7a8.03 8.03 0 0 0 0 11.3l39.6 39.6c3.1 3.1 8.2 3.1 11.3 0l226.4-226.4c3.1-3.1 3.1-8.2 0-11.3l-39.5-39.6z"></path></svg></i></a></div></div><div class="TipJarModal-fields"><div class="TipJarModal-fields-row"><div class="ant-row ant-form-item CopyInput TipJarModal-fields-row-address"><div class="ant-form-item-label"><label class="" title="Address">Address</label></div><div class="ant-form-item-control-wrapper"><div class="ant-form-item-control"><span class="ant-form-item-children"><input readonly="" type="text" class="ant-input" value="zs1xzymv205x8hhn8kt3pu43c6knjlelvxfgzgsyyus9yxhmdvqeu0yj0m2knzd3p93slsygkp94rz"><button type="button" class="ant-btn ant-btn-icon-only"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></span></div></div></div></div><div class="TipJarModal-fields-row"><div class="ant-row ant-form-item ant-form-item-with-help CopyInput"><div class="ant-form-item-label"><label class="" title="Zcash CLI command">Zcash CLI command</label></div><div class="ant-form-item-control-wrapper"><div class="ant-form-item-control"><span class="ant-form-item-children"><input readonly="" type="text" class="ant-input" value="zcash-cli z_sendmany YOUR_ADDRESS '[{"address":"zs1xzymv205x8hhn8kt3pu43c6knjlelvxfgzgsyyus9yxhmdvqeu0yj0m2knzd3p93slsygkp94rz","amount":0.2}]'"><button type="button" class="ant-btn ant-btn-icon-only"><i aria-label="icon: copy" class="anticon anticon-copy"><svg viewBox="64 64 896 896" class="" data-icon="copy" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 64H296c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h496v688c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V96c0-17.7-14.3-32-32-32zM704 192H192c-17.7 0-32 14.3-32 32v530.7c0 8.5 3.4 16.6 9.4 22.6l173.3 173.3c2.2 2.2 4.7 4 7.4 5.5v1.9h4.2c3.5 1.3 7.2 2 11 2H704c17.7 0 32-14.3 32-32V224c0-17.7-14.3-32-32-32zM350 856.2L263.9 770H350v86.2zM664 888H414V746c0-22.1-17.9-40-40-40H232V264h432v624z"></path></svg></i></button></span><div class="ant-form-explain">Make sure you replace YOUR_ADDRESS with your actual address</div></div></div></div></div></div></div></div><div class="ant-modal-footer"><button type="button" class="ant-btn ant-btn-primary"><span>Done</span></button></div></div><div tabindex="0" style="width: 0px; height: 0px; overflow: hidden;">sentinelEnd</div></div>--} - edit in client/src/Aftok/Billing.purs at line 33
, createBillable - edit in client/src/Aftok/Billing.purs at line 69
- replacement in client/src/Aftok/Billing.purs at line 157
{ createBillable: { createBillable: createBillable }{ createBillable: Create.apiCapability - edit in client/src/Aftok/HTML/Classes.purs at line 43[4.3987]
formGroup :: ClassNameformGroup = ClassName "form-group"formControlSm :: ClassNameformControlSm = ClassName "form-control-sm" - replacement in client/src/Aftok/Modals.purs at line 25
modal ::modalWithSave :: - replacement in client/src/Aftok/Modals.purs at line 32
modal modalId title submit contents =modalWithSave modalId title submit contents = - replacement in client/src/Aftok/Modals.purs at line 54
[ HH.span [ARIA.hidden "true"] [HH.text "×"]][ HH.span [ARIA.hidden "true"] [HH.text "×"]] - replacement in client/src/Aftok/Zcash.purs at line 6
import Data.Fixed (Fixed, P1000000, TenTimes)import Data.BigInt (toString) as BigIntimport Data.Fixed (Fixed, P1000000, TenTimes, fromInt, numerator)import Data.Fixed (toString) as Fixed - edit in client/src/Aftok/Zcash.purs at line 17
zatsString :: Zatoshi -> StringzatsString (Zatoshi z) = BigInt.toString z - edit in client/src/Aftok/Zcash.purs at line 30
zecString :: ZEC -> StringzecString (ZEC z) = Fixed.toString z - edit in client/src/Aftok/Zcash.purs at line 34[4.2065]
toZatoshi :: ZEC -> ZatoshitoZatoshi (ZEC z) =Zatoshi (numerator z) - edit in client/src/Main.purs at line 46
billing = Billing.apiCapability - edit in client/src/Main.purs at line 49
billing = Billing.mockCapability