Skip to content

Commit

Permalink
new: add recipient memo for transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
Seddik authored and Seddik committed Jun 21, 2024
1 parent 66504c7 commit 63c3a68
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 67 deletions.
18 changes: 13 additions & 5 deletions src/components/MoneyRequestModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
:selectedRecipient="selectedRecipient"
:config="config"
@update:amount="(x) => (amount = x)"
@update:message="(x) => (message = x)"
@update:senderMemo="(x) => (senderMemo = x)"
@update:recipientMemo="(x) => (recipientMemo = x)"
@update:isValid="(x) => (isValid = x)"
/>
</section>
Expand Down Expand Up @@ -72,7 +73,8 @@
rp: userProfile.id,
rpb: $modal.args.value[0].account.id,
amount: amount,
message: message,
senderMemo: senderMemo,
recipientMemo: recipientMemo,
})
"
/>
Expand Down Expand Up @@ -119,7 +121,8 @@
data() {
return {
amount: null,
message: null,
senderMemo: null,
recipientMemo: null,
isValid: false,
config: {},
}
Expand All @@ -128,9 +131,14 @@
...mapModuleState("lokapi", ["userProfile"]),
},
watch: {
message: {
senderMemo: {
handler(newVal, oldVal) {
this.config.message = newVal
this.config.senderMemo = newVal
},
},
recipientMemo: {
handler(newVal, oldVal) {
this.config.recipientMemo = newVal
},
},
amount: {
Expand Down
128 changes: 112 additions & 16 deletions src/components/MoneyTransaction.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,64 @@
<div class="notification is-danger is-light" v-if="parentErrors">
{{ parentErrors }}
</div>
<div class="is-flex mt-5">
<h2 class="frame3-sub-title">
{{ $gettext("Payment memo") }}
</h2>
</div>
<div v-if="!isReconversion" class="is-flex mt-3">
<div class="switch-centered">
<label class="switch">
<input
type="checkbox"
v-model="isCopyMemo"
:checked="isCopyMemo"
@click="handleSwitch"
/>
<span class="slider round"></span>
</label>
</div>
<div class="ml-2 switch-centered">
{{ $gettext("Copy memo") }}
</div>
</div>
<textarea
@input="handleMessageInput()"
v-model="message"
class="custom-textarea textarea mt-5"
@input="handleSenderMemoInput()"
v-model="senderMemo"
class="custom-textarea textarea mt-1"
:class="{
'is-danger': errors.message,
'is-danger': errors.senderMemo,
}"
:placeholder="$gettext('Add a memo (optional)')"
:placeholder="$gettext('Add a payment memo (optional)')"
></textarea>
<div class="notification is-danger is-light mt-2" v-if="errors.message">
{{ errors.message }}
<div
class="notification is-danger is-light mt-2"
v-if="errors.senderMemo"
>
{{ errors.senderMemo }}
</div>
<div v-if="!isReconversion">
<h2 class="frame3-sub-title mt-3 mb-3">
{{ $gettext("Reference for recipient") }}
</h2>
<textarea
@change="handleRecipientMemoInput()"
v-model="recipientMemo"
class="custom-textarea textarea mt-1"
:class="{
'is-danger': errors.recipientMemo,
}"
:placeholder="
$gettext('Add a reference for the recipient (optional)')
"
>
</textarea>
<div
class="notification is-danger is-light mt-2"
v-if="errors.recipientMemo"
>
{{ errors.recipientMemo }}
</div>
</div>
</div>
</div>
Expand All @@ -77,30 +124,40 @@
RecipientItem,
BankAccountItem,
},
emits: ["update:amount", "update:message", "update:isValid"],
emits: [
"update:amount",
"update:senderMemo",
"update:recipientMemo",
"update:isValid",
],
props: {
account: Object,
selectedRecipient: Object,
directionTransfer: String,
config: Object,
parentErrors: String,
isReconversion: Boolean,
},
data() {
return {
amount: null,
message: null,
senderMomo: null,
recipientMemo: null,
isCopyMemo: false,
errors: {
amountLength: true,
amount: false,
message: false,
senderMomo: false,
recipientMemo: false,
},
}
},
mounted() {
this.setFocus("amountRequested")
if (this.config?.amount) {
this.amount = this.config?.amount
this.message = this.config?.message
this.senderMemo = this.config?.senderMemo
this.recipientMemo = this.config?.recipientMemo
this.errors.amountLength = this.amount?.length === 0
}
},
Expand All @@ -116,6 +173,18 @@
this.$emit("update:isValid", newVal)
},
},
recipientMemo(newVal, oldVal) {
if (this.recipientMemo != this.senderMemo) {
this.isCopyMemo = false
}
if (this.recipientMemo.length > 50) {
this.errors.recipientMemo = this.$gettext(
"the message description is too long"
)
return
}
this.errors.recipientMemo = false
},
},
methods: {
handleAmountInput() {
Expand All @@ -134,15 +203,30 @@
this.$emit("update:amount", parseFloat(this.amount).toFixed(2))
this.errors.amount = false
},
handleMessageInput() {
if (this.message.length > 50) {
this.errors.message = this.$gettext(
handleSenderMemoInput() {
if (this.senderMemo.length > 50) {
this.errors.senderMemo = this.$gettext(
"the message description is too long"
)
return
}
if (this.isCopyMemo) {
this.recipientMemo = this.senderMemo
}
this.$emit("update:senderMemo", this.senderMemo)
this.errors.senderMemo = false
},
handleRecipientMemoInput() {
if (this.recipientMemo.length > 50) {
this.errors.recipientMemo = this.$gettext(
"the message description is too long"
)
return
}
this.$emit("update:message", this.message)
this.errors.message = false
if (this.recipientMemo != this.senderMemo) {
this.isCopyMemo = false
}
this.$emit("update:recipientMemo", this.recipientMemo)
},
setFocus(refLabel: string) {
this.$nextTick(() => {
Expand All @@ -151,12 +235,19 @@
ref.select()
})
},
handleSwitch(event: any) {
this.isCopyMemo = event.target.checked
if (this.isCopyMemo) {
this.recipientMemo = this.senderMemo
}
},
},
})
export default class MoneyTransaction extends Vue {}
</script>
<style lang="scss" scoped>
@import "@/assets/custom-variables";
@import "@/assets/switch-prefs";
.search-area {
background: #f0faf9;
Expand Down Expand Up @@ -231,4 +322,9 @@
width: fit-content;
margin: auto;
}
.memo-checkbox {
width: 2em;
height: 2em;
margin-top: 0.7em;
}
</style>
20 changes: 14 additions & 6 deletions src/components/MoneyTransferModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,10 @@
:selectedRecipient="selectedRecipient"
:config="config"
:parentErrors="errors"
:isReconversion="isReconversion"
@update:amount="(x) => (amount = x)"
@update:message="(x) => (message = x)"
@update:senderMemo="(x) => (senderMemo = x)"
@update:recipientMemo="(x) => (recipientMemo = x)"
@update:isValid="(x) => (isValid = x)"
/>
</section>
Expand Down Expand Up @@ -196,7 +198,8 @@
ownSelectedAccount: null,
amount: null,
config: {},
message: null,
senderMemo: null,
recipientMemo: null,
errors: false,
account: null,
isValid: false,
Expand Down Expand Up @@ -301,7 +304,8 @@
await this.toPaymentStage({
recipient,
amount: resultData.amount,
message: resultData.message,
senderMemo: resultData.senderMemo,
recipientMemo: resultData.recipientMemo,
})
},
handleClickRecipient(recipient: any): void {
Expand All @@ -318,8 +322,10 @@
this.$modal.next()
this.errors = false
this.amount = config?.amount || null
this.message = config?.message
this.sendermemo = config?.senderMemo
this.recipientMemo = config?.recipientMemo
this.config = config
this.transactionId = config.transactionId
},
async sendTransaction(): Promise<void> {
if (this.transferOngoing) {
Expand Down Expand Up @@ -355,12 +361,13 @@
return
}
// XXXvlab: normalize output (in particular: "4.1" => "4.10")
realBal = parseFloat(realBal).toFixed(2)
const amount_cents = parseInt(this.amount.replace(".", ""))
const realBal_cents = parseInt(realBal.replace(".", ""))
const bal_cents = parseInt(
this.ownSelectedAccount.bal.toFixed(2).replace(".", "")
)
if (amount_cents > bal_cents) {
this.errors = this.$gettext("Insufficient balance")
return
Expand Down Expand Up @@ -389,7 +396,8 @@
try {
payment = await this.selectedRecipient.transfer(
this.amount.toString(),
this.message
this.senderMemo,
this.recipientMemo
)
} catch (err: any) {
if (err instanceof LokapiExc.PaymentConfirmationMissing) {
Expand Down
Loading

0 comments on commit 63c3a68

Please sign in to comment.