forked from jsnbuchanan/crowd-funder-for-time-pwa
Feature: giver-recipient validation
- Ensures person-to-person gifting won't allow the same entity as giver and recipient - Disable user item selection if it would create conflict - Error messaging fallback
This commit is contained in:
@@ -80,16 +80,29 @@
|
|||||||
stepType === 'recipient' ||
|
stepType === 'recipient' ||
|
||||||
(stepType === 'giver' && isFromProjectView)
|
(stepType === 'giver' && isFromProjectView)
|
||||||
"
|
"
|
||||||
class="cursor-pointer"
|
:class="{
|
||||||
|
'cursor-pointer': !wouldCreateConflict(activeDid),
|
||||||
|
'cursor-not-allowed opacity-50': wouldCreateConflict(activeDid)
|
||||||
|
}"
|
||||||
@click="
|
@click="
|
||||||
stepType === 'recipient'
|
!wouldCreateConflict(activeDid) &&
|
||||||
|
(stepType === 'recipient'
|
||||||
? selectRecipient({ did: activeDid, name: 'You' })
|
? selectRecipient({ did: activeDid, name: 'You' })
|
||||||
: selectGiver({ did: activeDid, name: 'You' })
|
: selectGiver({ did: activeDid, name: 'You' }))
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<font-awesome icon="hand" class="text-blue-500 text-5xl mb-1" />
|
<font-awesome
|
||||||
|
:class="{
|
||||||
|
'text-blue-500 text-5xl mb-1': !wouldCreateConflict(activeDid),
|
||||||
|
'text-slate-400 text-5xl mb-1': wouldCreateConflict(activeDid)
|
||||||
|
}"
|
||||||
|
icon="hand"
|
||||||
|
/>
|
||||||
<h3
|
<h3
|
||||||
class="text-xs text-blue-500 font-medium text-ellipsis whitespace-nowrap overflow-hidden"
|
:class="{
|
||||||
|
'text-xs text-blue-500 font-medium text-ellipsis whitespace-nowrap overflow-hidden': !wouldCreateConflict(activeDid),
|
||||||
|
'text-xs text-slate-400 font-medium text-ellipsis whitespace-nowrap overflow-hidden': wouldCreateConflict(activeDid)
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
You
|
You
|
||||||
</h3>
|
</h3>
|
||||||
@@ -119,11 +132,15 @@
|
|||||||
<li
|
<li
|
||||||
v-for="contact in allContacts.slice(0, 10)"
|
v-for="contact in allContacts.slice(0, 10)"
|
||||||
:key="contact.did"
|
:key="contact.did"
|
||||||
class="cursor-pointer"
|
:class="{
|
||||||
|
'cursor-pointer': !wouldCreateConflict(contact.did),
|
||||||
|
'cursor-not-allowed opacity-50': wouldCreateConflict(contact.did)
|
||||||
|
}"
|
||||||
@click="
|
@click="
|
||||||
stepType === 'recipient'
|
!wouldCreateConflict(contact.did) &&
|
||||||
|
(stepType === 'recipient'
|
||||||
? selectRecipient(contact)
|
? selectRecipient(contact)
|
||||||
: selectGiver(contact)
|
: selectGiver(contact))
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div class="relative w-fit mx-auto">
|
<div class="relative w-fit mx-auto">
|
||||||
@@ -141,7 +158,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h3
|
<h3
|
||||||
class="text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden"
|
:class="{
|
||||||
|
'text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden': !wouldCreateConflict(contact.did),
|
||||||
|
'text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden text-slate-400': wouldCreateConflict(contact.did)
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
{{ contact.name || contact.did }}
|
{{ contact.name || contact.did }}
|
||||||
</h3>
|
</h3>
|
||||||
@@ -425,9 +445,22 @@
|
|||||||
@click="explainData()"
|
@click="explainData()"
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<!-- Conflict warning -->
|
||||||
|
<div v-if="hasPersonConflict" class="mb-4 p-3 bg-red-50 border border-red-200 rounded-md">
|
||||||
|
<p class="text-red-700 text-sm text-center">
|
||||||
|
<font-awesome icon="exclamation-triangle" class="fa-fw mr-1" />
|
||||||
|
Cannot record: Same person selected as both giver and recipient
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
|
||||||
<button
|
<button
|
||||||
class="block w-full text-center text-md uppercase font-bold bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-lg"
|
:disabled="hasPersonConflict"
|
||||||
|
:class="{
|
||||||
|
'block w-full text-center text-md uppercase font-bold bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-lg': !hasPersonConflict,
|
||||||
|
'block w-full text-center text-md uppercase font-bold bg-gradient-to-b from-slate-300 to-slate-500 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-slate-400 px-1.5 py-2 rounded-lg cursor-not-allowed': hasPersonConflict
|
||||||
|
}"
|
||||||
@click="confirm"
|
@click="confirm"
|
||||||
>
|
>
|
||||||
Sign & Send
|
Sign & Send
|
||||||
@@ -525,6 +558,39 @@ export default class GiftedDialog extends Vue {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Computed property to check if current selection would create a conflict
|
||||||
|
get hasPersonConflict() {
|
||||||
|
// Only check for conflicts when both entities are persons
|
||||||
|
if (this.giverEntityType !== "person" || this.recipientEntityType !== "person") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if giver and recipient are the same person
|
||||||
|
if (this.giver?.did && this.receiver?.did && this.giver.did === this.receiver.did) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Computed property to check if a contact would create a conflict when selected
|
||||||
|
wouldCreateConflict(contactDid: string) {
|
||||||
|
// Only check for conflicts when both entities are persons
|
||||||
|
if (this.giverEntityType !== "person" || this.recipientEntityType !== "person") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.stepType === "giver") {
|
||||||
|
// If selecting as giver, check if it conflicts with current recipient
|
||||||
|
return this.receiver?.did === contactDid;
|
||||||
|
} else if (this.stepType === "recipient") {
|
||||||
|
// If selecting as recipient, check if it conflicts with current giver
|
||||||
|
return this.giver?.did === contactDid;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
stepType = "giver";
|
stepType = "giver";
|
||||||
giverEntityType = "person" as "person" | "project";
|
giverEntityType = "person" as "person" | "project";
|
||||||
recipientEntityType = "person" as "person" | "project";
|
recipientEntityType = "person" as "person" | "project";
|
||||||
@@ -705,6 +771,20 @@ export default class GiftedDialog extends Vue {
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for person conflict
|
||||||
|
if (this.hasPersonConflict) {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: "Error",
|
||||||
|
text: "You cannot select the same person as both giver and recipient.",
|
||||||
|
},
|
||||||
|
3000,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.close();
|
this.close();
|
||||||
this.$notify(
|
this.$notify(
|
||||||
|
|||||||
Reference in New Issue
Block a user