@ -15,26 +15,25 @@ Raymer */
class = "block w-full rounded border border-slate-400 mb-2 px-3 py-2"
placeholder = "Description of what is offered"
/ >
< div class = "flex flex-row mt-2" >
< span :class ="unitCodeDisplayClasses" @click ="changeUnitCode()" >
{ { libsUtil . UNIT_SHORT [ amountUnitCode ] } }
< / span >
< div
v - if = "showDecrementButton"
: class = "controlButtonClasses"
@ click = "decrement()"
>
< font -awesome icon = "chevron-left" / >
< / div >
< input
v - model = "amountInput"
< div class = "flex mb-4" >
< AmountInput
: value = "parseFloat(amountInput) || 0"
: onUpdateValue = "handleAmountUpdate"
data - testId = "inputOfferAmount"
type = "number"
: class = "amountInputClasses"
/ >
< div :class ="incrementButtonClasses" @click ="increment()" >
< font -awesome icon = "chevron-right" / >
< / div >
< select
v - model = "amountUnitCode"
class = "flex-1 rounded border border-slate-400 ms-2 px-3 py-2"
>
< option
v - for = "(displayName, code) in unitOptions"
: key = "code"
: value = "code"
>
{ { displayName } }
< / option >
< / select >
< / div >
< div class = "mt-4 flex justify-center" >
< span >
@ -73,10 +72,15 @@ import {
NOTIFY_OFFER_CREATION_ERROR ,
NOTIFY_OFFER_SUCCESS ,
NOTIFY_OFFER_SUBMISSION_ERROR ,
NOTIFY_OFFER_ERROR_NEGATIVE_AMOUNT ,
} from "@/constants/notifications" ;
import AmountInput from "./AmountInput.vue" ;
@ Component ( {
mixins : [ PlatformServiceMixin ] ,
components : {
AmountInput ,
} ,
} )
export default class OfferDialog extends Vue {
@ Prop projectId ? : string ;
@ -122,35 +126,10 @@ export default class OfferDialog extends Vue {
}
/ * *
* CSS classes for unit code selector and increment / decrement buttons
* Reduces template complexity for repeated border and styling patterns
* /
get controlButtonClasses ( ) : string {
return "border border-r-0 border-slate-400 bg-slate-200 px-4 py-2" ;
}
/ * *
* CSS classes for unit code display span
* Reduces template complexity for unit code button styling
* Computed property to get unit options for the select dropdown
* /
get unitCodeDisplayClasses ( ) : string {
return "rounded-l border border-r-0 border-slate-400 bg-slate-200 w-1/3 text-center text-blue-500 px-2 py-2" ;
}
/ * *
* CSS classes for amount input field
* Reduces template complexity for input styling
* /
get amountInputClasses ( ) : string {
return "w-full border border-r-0 border-slate-400 px-2 py-2 text-center" ;
}
/ * *
* CSS classes for the right - most increment button
* Reduces template complexity for border styling
* /
get incrementButtonClasses ( ) : string {
return "rounded-r border border-slate-400 bg-slate-200 px-4 py-2" ;
get unitOptions ( ) {
return this . libsUtil . UNIT_SHORT ;
}
/ * *
@ -173,13 +152,7 @@ export default class OfferDialog extends Vue {
} ;
}
/ * *
* Whether the decrement button should be visible
* Encapsulates conditional logic from template
* /
get showDecrementButton ( ) : boolean {
return this . amountInput !== "0" ;
}
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
/ / C O M P O N E N T M E T H O D S
@ -226,30 +199,14 @@ export default class OfferDialog extends Vue {
this . visible = false ;
}
/ * *
* Cycle through available unit codes
* /
changeUnitCode ( ) {
const units = Object . keys ( this . libsUtil . UNIT_SHORT ) ;
const index = units . indexOf ( this . amountUnitCode ) ;
this . amountUnitCode = units [ ( index + 1 ) % units . length ] ;
}
/ * *
* Increment the amount input
* /
increment ( ) {
this . amountInput = ` ${ ( parseFloat ( this . amountInput ) || 0 ) + 1 } ` ;
}
/ * *
* Decrement the amount input
* Handle amount updates from AmountInput component
* @ param value - New amount value
* /
decrement ( ) {
this . amountInput = ` ${ Math . max (
0 ,
( parseFloat ( this . amountInput ) || 1 ) - 1 ,
) } ` ;
handleAmountUpdate ( value : number ) {
this . amountInput = value . toString ( ) ;
}
/ * *
@ -273,6 +230,28 @@ export default class OfferDialog extends Vue {
* Confirm and submit the offer
* /
async confirm ( ) {
if ( ! this . activeDid ) {
this . notify . error ( NOTIFY_OFFER_IDENTITY_REQUIRED . message , TIMEOUTS . LONG ) ;
return ;
}
if ( parseFloat ( this . amountInput ) < 0 ) {
this . notify . error (
NOTIFY_OFFER_ERROR_NEGATIVE_AMOUNT . message ,
TIMEOUTS . SHORT ,
) ;
return ;
}
if ( ! this . description && ! parseFloat ( this . amountInput ) ) {
const message = NOTIFY_OFFER_DESCRIPTION_REQUIRED . message . replace (
"{unit}" ,
this . libsUtil . UNIT_LONG [ this . amountUnitCode ] ,
) ;
this . notify . error ( message , TIMEOUTS . SHORT ) ;
return ;
}
this . close ( ) ;
this . notify . toast ( NOTIFY_OFFER_RECORDING . text , undefined , TIMEOUTS . BRIEF ) ;
@ -301,20 +280,6 @@ export default class OfferDialog extends Vue {
unitCode : string = "HUR" ,
expirationDateInput ? : string ,
) {
if ( ! this . activeDid ) {
this . notify . error ( NOTIFY_OFFER_IDENTITY_REQUIRED . message , TIMEOUTS . LONG ) ;
return ;
}
if ( ! description && ! amount ) {
const message = NOTIFY_OFFER_DESCRIPTION_REQUIRED . message . replace (
"{unit}" ,
this . libsUtil . UNIT_LONG [ unitCode ] ,
) ;
this . notify . error ( message , TIMEOUTS . MODAL ) ;
return ;
}
try {
const result = await createAndSubmitOffer (
this . axios ,
@ -363,7 +328,7 @@ export default class OfferDialog extends Vue {
display : flex ;
justify - content : center ;
align - items : center ;
z - index : 100 0;
z - index : 5 0;
}
. dialog {