|
@ -15,26 +15,25 @@ Raymer */ |
|
|
class="block w-full rounded border border-slate-400 mb-2 px-3 py-2" |
|
|
class="block w-full rounded border border-slate-400 mb-2 px-3 py-2" |
|
|
placeholder="Description of what is offered" |
|
|
placeholder="Description of what is offered" |
|
|
/> |
|
|
/> |
|
|
<div class="flex flex-row mt-2"> |
|
|
<div class="flex mb-4"> |
|
|
<span :class="unitCodeDisplayClasses" @click="changeUnitCode()"> |
|
|
<AmountInput |
|
|
{{ libsUtil.UNIT_SHORT[amountUnitCode] }} |
|
|
:value="parseFloat(amountInput) || 0" |
|
|
</span> |
|
|
:onUpdateValue="handleAmountUpdate" |
|
|
<div |
|
|
|
|
|
v-if="showDecrementButton" |
|
|
|
|
|
:class="controlButtonClasses" |
|
|
|
|
|
@click="decrement()" |
|
|
|
|
|
> |
|
|
|
|
|
<font-awesome icon="chevron-left" /> |
|
|
|
|
|
</div> |
|
|
|
|
|
<input |
|
|
|
|
|
v-model="amountInput" |
|
|
|
|
|
data-testId="inputOfferAmount" |
|
|
data-testId="inputOfferAmount" |
|
|
type="number" |
|
|
|
|
|
:class="amountInputClasses" |
|
|
|
|
|
/> |
|
|
/> |
|
|
<div :class="incrementButtonClasses" @click="increment()"> |
|
|
|
|
|
<font-awesome icon="chevron-right" /> |
|
|
<select |
|
|
</div> |
|
|
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> |
|
|
<div class="mt-4 flex justify-center"> |
|
|
<div class="mt-4 flex justify-center"> |
|
|
<span> |
|
|
<span> |
|
@ -73,10 +72,15 @@ import { |
|
|
NOTIFY_OFFER_CREATION_ERROR, |
|
|
NOTIFY_OFFER_CREATION_ERROR, |
|
|
NOTIFY_OFFER_SUCCESS, |
|
|
NOTIFY_OFFER_SUCCESS, |
|
|
NOTIFY_OFFER_SUBMISSION_ERROR, |
|
|
NOTIFY_OFFER_SUBMISSION_ERROR, |
|
|
|
|
|
NOTIFY_OFFER_ERROR_NEGATIVE_AMOUNT, |
|
|
} from "@/constants/notifications"; |
|
|
} from "@/constants/notifications"; |
|
|
|
|
|
import AmountInput from "./AmountInput.vue"; |
|
|
|
|
|
|
|
|
@Component({ |
|
|
@Component({ |
|
|
mixins: [PlatformServiceMixin], |
|
|
mixins: [PlatformServiceMixin], |
|
|
|
|
|
components: { |
|
|
|
|
|
AmountInput, |
|
|
|
|
|
}, |
|
|
}) |
|
|
}) |
|
|
export default class OfferDialog extends Vue { |
|
|
export default class OfferDialog extends Vue { |
|
|
@Prop projectId?: string; |
|
|
@Prop projectId?: string; |
|
@ -122,35 +126,10 @@ export default class OfferDialog extends Vue { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* CSS classes for unit code selector and increment/decrement buttons |
|
|
* Computed property to get unit options for the select dropdown |
|
|
* 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 |
|
|
|
|
|
*/ |
|
|
*/ |
|
|
get unitCodeDisplayClasses(): string { |
|
|
get unitOptions() { |
|
|
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"; |
|
|
return this.libsUtil.UNIT_SHORT; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 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"; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
@ -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"; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// ================================================= |
|
|
// ================================================= |
|
|
// COMPONENT METHODS |
|
|
// COMPONENT METHODS |
|
@ -226,30 +199,14 @@ export default class OfferDialog extends Vue { |
|
|
this.visible = false; |
|
|
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() { |
|
|
handleAmountUpdate(value: number) { |
|
|
this.amountInput = `${Math.max( |
|
|
this.amountInput = value.toString(); |
|
|
0, |
|
|
|
|
|
(parseFloat(this.amountInput) || 1) - 1, |
|
|
|
|
|
)}`; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
@ -273,6 +230,28 @@ export default class OfferDialog extends Vue { |
|
|
* Confirm and submit the offer |
|
|
* Confirm and submit the offer |
|
|
*/ |
|
|
*/ |
|
|
async confirm() { |
|
|
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.close(); |
|
|
this.notify.toast(NOTIFY_OFFER_RECORDING.text, undefined, TIMEOUTS.BRIEF); |
|
|
this.notify.toast(NOTIFY_OFFER_RECORDING.text, undefined, TIMEOUTS.BRIEF); |
|
|
|
|
|
|
|
@ -301,20 +280,6 @@ export default class OfferDialog extends Vue { |
|
|
unitCode: string = "HUR", |
|
|
unitCode: string = "HUR", |
|
|
expirationDateInput?: string, |
|
|
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 { |
|
|
try { |
|
|
const result = await createAndSubmitOffer( |
|
|
const result = await createAndSubmitOffer( |
|
|
this.axios, |
|
|
this.axios, |
|
@ -363,7 +328,7 @@ export default class OfferDialog extends Vue { |
|
|
display: flex; |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
justify-content: center; |
|
|
align-items: center; |
|
|
align-items: center; |
|
|
z-index: 1000; |
|
|
z-index: 50; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.dialog { |
|
|
.dialog { |
|
|