@ -3,63 +3,104 @@
< div class = "dialog" >
<!-- Step 1 : Giver -- >
< div id = "sectionGiftedGiver" v-show ="currentStep === 1" >
< label class = "block font-bold mb-4" > Choose a person to receive from : < / label >
<!-- Quick - pick grid -- >
< ul
class = "grid grid-cols-4 sm:grid-cols-5 md:grid-cols-6 gap-x-2 gap-y-4 text-center mb-4"
>
< li
@ click = "selectGiver()"
class = "cursor-pointer"
>
< font -awesome icon = "circle-question" class = "text-slate-400 text-5xl mb-1" / >
< h3
class = "text-xs text-slate-500 font-medium italic text-ellipsis whitespace-nowrap overflow-hidden"
< label class = "block font-bold mb-4" >
{ { showProjects ? 'Choose a project to benefit from:' : 'Choose a person to receive from:' } }
< / label >
<!-- Unified Quick - pick grid for People and Projects -- >
< ul : class = "showProjects ? 'grid grid-cols-3 md:grid-cols-4 gap-x-2 gap-y-4 text-center mb-4' : 'grid grid-cols-4 sm:grid-cols-5 md:grid-cols-6 gap-x-2 gap-y-4 text-center mb-4'" >
< template v-if ="showProjects" >
< li
v - for = "project in projects.slice(0, 7)"
: key = "project.handleId"
@ click = "selectProject(project)"
class = "cursor-pointer"
>
Unnamed
< / h3 >
< / li >
< li v-if ="allContacts.length === 0" class="text-xs text-slate-500 italic" >
( Add friends to see more people worthy of recognition . )
< / li >
< li
v - for = "contact in allContacts.slice(0, 10)"
: key = "contact.did"
@ click = "selectGiver(contact)"
class = "cursor-pointer"
>
< div class = "relative w-fit mx-auto" >
< EntityIcon
: contact = "contact"
class = "!size-[3rem] mx-auto border border-slate-300 bg-white overflow-hidden rounded-full mb-1"
/ >
< div
class = "rounded-full bg-slate-400 absolute bottom-0 right-0 p-1 translate-x-1/3"
>
< font -awesome icon = "clock" class = "block text-white text-xs w-[1em]" / >
< div class = "relative w-fit mx-auto" >
< ProjectIcon
: entity - id = "project.handleId"
: icon - size = "48"
: image - url = "project.image"
class = "!size-[3rem] mx-auto border border-slate-300 bg-white overflow-hidden rounded-full mb-1"
/ >
< / div >
< h3 class = "text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden" >
{ { project . name } }
< / h3 >
< div class = "text-xs text-slate-500 truncate" >
< font -awesome icon = "user" class = "fa-fw text-slate-400" / >
{ { didInfo ( project . issuerDid , activeDid , allMyDids , allContacts ) } }
< / div >
< / div >
< h3
class = "text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden"
< / li >
< li v-if ="projects.length === 0" class="text-xs text-slate-500 italic col-span-full" >
( No projects found . )
< / li >
< li v-if ="projects.length > 0" >
< router -link
: to = "{ name: 'discover' }"
class = "cursor-pointer"
>
< font -awesome icon = "circle-right" class = "text-blue-500 text-5xl mb-1" / >
< h3 class = "text-xs text-slate-500 font-medium italic text-ellipsis whitespace-nowrap overflow-hidden" >
Show All
< / h3 >
< / r o u t e r - l i n k >
< / li >
< / template >
< template v-else >
< li
v - if = "isFromProjectView && activeDid"
@ click = "selectGiver({ did: activeDid, name: 'You' })"
class = "cursor-pointer"
>
{ { contact . name || contact . did } }
< / h3 >
< / li >
< li v-if ="allContacts.length > 0" >
< router -link
: to = "{ name: 'contact-gift' }"
< font -awesome icon = "hand" class = "text-blue-500 text-5xl mb-1" / >
< h3 class = "text-xs text-blue-500 font-medium text-ellipsis whitespace-nowrap overflow-hidden" >
You
< / h3 >
< / li >
< li
@ click = "selectGiver()"
class = "cursor-pointer"
>
< font -awesome icon = "circle-right" class = "text-blue-500 text-5xl mb-1" / >
< h3
class = "text-xs text-slate-500 font-medium italic text-ellipsis whitespace-nowrap overflow-hidden"
>
Show All
< font -awesome icon = "circle-question" class = "text-slate-400 text-5xl mb-1" / >
< h3 class = "text-xs text-slate-500 font-medium italic text-ellipsis whitespace-nowrap overflow-hidden" >
Unnamed
< / h3 >
< / r o u t e r - l i n k >
< / li >
< / li >
< li v-if ="allContacts.length === 0" class="text-xs text-slate-500 italic col-span-full" >
( Add friends to see more people worthy of recognition . )
< / li >
< li
v - for = "contact in allContacts.slice(0, 10)"
: key = "contact.did"
@ click = "selectGiver(contact)"
class = "cursor-pointer"
>
< div class = "relative w-fit mx-auto" >
< EntityIcon
: contact = "contact"
class = "!size-[3rem] mx-auto border border-slate-300 bg-white overflow-hidden rounded-full mb-1"
/ >
< div class = "rounded-full bg-slate-400 absolute bottom-0 right-0 p-1 translate-x-1/3" >
< font -awesome icon = "clock" class = "block text-white text-xs w-[1em]" / >
< / div >
< / div >
< h3 class = "text-xs font-medium text-ellipsis whitespace-nowrap overflow-hidden" >
{ { contact . name || contact . did } }
< / h3 >
< / li >
< li v-if ="allContacts.length > 0" >
< router -link
: to = "{ name: 'contact-gift' }"
class = "cursor-pointer"
>
< font -awesome icon = "circle-right" class = "text-blue-500 text-5xl mb-1" / >
< h3 class = "text-xs text-slate-500 font-medium italic text-ellipsis whitespace-nowrap overflow-hidden" >
Show All
< / h3 >
< / r o u t e r - l i n k >
< / li >
< / template >
< / ul >
< button
@ -72,27 +113,72 @@
<!-- Step 2 : Gift -- >
< div id = "sectionGiftedGift" v-show ="currentStep === 2" >
< button class = "w-full flex items-center gap-2 bg-slate-100 border border-slate-300 rounded-md p-2 mb-4" @click ="goBackToStep1" >
< button
v - if = "!fromProjectId"
class = "w-full flex items-center gap-2 bg-slate-100 border border-slate-300 rounded-md p-2 mb-4"
@ click = "goBackToStep1"
>
< div >
< EntityIcon
v - if = "giver?.did"
: contact = "giver"
class = "rounded-full bg-white overflow-hidden !size-[2rem] object-cover"
/ >
< font -awesome
v - else
icon = "circle-question"
class = "text-slate-400 text-3xl"
/ >
< / div >
< div class = "text-start min-w-0" >
< p class = "text-xs text-slate-500 leading-1 -mb-1 uppercase" > Received from : < / p >
< h3 class = "font-semibold truncate" > { { giver ? . name || 'Unnamed' } } < / h3 >
< / div >
< p class = "ms-auto text-sm uppercase font-medium pe-2" > Change < / p >
< / button >
< template v-if ="showProjects" >
< ProjectIcon
v - if = "giver?.handleId"
: entity - id = "giver.handleId"
: icon - size = "32"
: image - url = "giver.image"
class = "rounded-full bg-white overflow-hidden !size-[2rem] object-cover"
/ >
< / template >
< template v-else >
< EntityIcon
v - if = "giver?.did"
: contact = "giver"
class = "rounded-full bg-white overflow-hidden !size-[2rem] object-cover"
/ >
< font -awesome
v - else
icon = "circle-question"
class = "text-slate-400 text-3xl"
/ >
< / template >
< / div >
< div class = "text-start min-w-0" >
< p class = "text-xs text-slate-500 leading-1 -mb-1 uppercase" > { { showProjects ? 'Benefited from:' : 'Received from:' } } < / p >
< h3 class = "font-semibold truncate" > { { giver ? . name || 'Unnamed' } } < / h3 >
< / div >
< p class = "ms-auto text-sm uppercase font-medium pe-2" > Change < / p >
< / button >
< div v -else class = "w-full flex items-center gap-2 bg-slate-100 border border-slate-300 rounded-md p-2 mb-4" >
< div >
< template v-if ="showProjects" >
< ProjectIcon
v - if = "giver?.handleId"
: entity - id = "giver.handleId"
: icon - size = "32"
: image - url = "giver.image"
class = "rounded-full bg-white overflow-hidden !size-[2rem] object-cover"
/ >
< / template >
< template v-else >
< EntityIcon
v - if = "giver?.did"
: contact = "giver"
class = "rounded-full bg-white overflow-hidden !size-[2rem] object-cover"
/ >
< font -awesome
v - else
icon = "circle-question"
class = "text-slate-400 text-3xl"
/ >
< / template >
< / div >
< div class = "text-start min-w-0" >
< p class = "text-xs text-slate-500 leading-1 -mb-1 uppercase" > { { showProjects ? 'Benefited from:' : 'Received from:' } } < / p >
< h3 class = "font-semibold truncate" > { { giver ? . name || 'Unnamed' } } < / h3 >
< / div >
< / div >
< input
v - model = "description"
type = "text"
@ -182,6 +268,7 @@ import {
createAndSubmitGive ,
didInfo ,
serverMessageForUser ,
getHeaders ,
} from "../libs/endorserServer" ;
import * as libsUtil from "../libs/util" ;
import { db , retrieveSettingsForActiveAccount } from "../db/index" ;
@ -191,10 +278,13 @@ import { retrieveAccountDids } from "../libs/util";
import { logger } from "../utils/logger" ;
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory" ;
import EntityIcon from "../components/EntityIcon.vue" ;
import ProjectIcon from "../components/ProjectIcon.vue" ;
import { PlanData } from "../interfaces/records" ;
@ Component ( {
components : {
EntityIcon ,
ProjectIcon ,
} ,
} )
export default class GiftedDialog extends Vue {
@ -202,6 +292,8 @@ export default class GiftedDialog extends Vue {
@ Prop ( ) fromProjectId = "" ;
@ Prop ( ) toProjectId = "" ;
@ Prop ( { default : false } ) showProjects = false ;
@ Prop ( ) isFromProjectView = false ;
activeDid = "" ;
allContacts : Array < Contact > = [ ] ;
@ -222,6 +314,10 @@ export default class GiftedDialog extends Vue {
libsUtil = libsUtil ;
projects : PlanData [ ] = [ ] ;
didInfo = didInfo ;
async open (
giver ? : libsUtil . GiverReceiverInputInfo ,
receiver ? : libsUtil . GiverReceiverInputInfo ,
@ -234,7 +330,6 @@ export default class GiftedDialog extends Vue {
this . giver = giver ;
this . prompt = prompt || "" ;
this . receiver = receiver ;
/ / i f w e s h o w " g i v e n t o u s e r " s e l e c t i o n , d e f a u l t c h e c k b o x t o t r u e
this . amountInput = "0" ;
this . callbackOnSuccess = callbackOnSuccess ;
this . offerId = offerId || "" ;
@ -269,7 +364,10 @@ export default class GiftedDialog extends Vue {
this . allContacts ,
) ;
}
/ / e s l i n t - d i s a b l e - n e x t - l i n e @ t y p e s c r i p t - e s l i n t / n o - e x p l i c i t - a n y
if ( this . showProjects ) {
await this . loadProjects ( ) ;
}
} catch ( err : any ) {
logger . error ( "Error retrieving settings from database:" , err ) ;
this . $notify (
@ -404,7 +502,7 @@ export default class GiftedDialog extends Vue {
this . axios ,
this . apiServer ,
this . activeDid ,
giverDid as string ,
this . showProjects ? undefined : giverDid as string ,
recipientDid as string ,
description ,
amount ,
@ -413,7 +511,7 @@ export default class GiftedDialog extends Vue {
this . offerId ,
false ,
undefined ,
this . fromProjectI d,
this . showProjects ? this . giver ? . handleId : undefine d,
) ;
if ( ! result . success ) {
@ -506,6 +604,49 @@ export default class GiftedDialog extends Vue {
goBackToStep1 ( ) {
this . currentStep = 1 ;
}
async loadProjects ( ) {
try {
const response = await fetch ( this . apiServer + "/api/v2/report/plans" , {
method : "GET" ,
headers : await getHeaders ( this . activeDid ) ,
} ) ;
if ( response . status !== 200 ) {
throw new Error ( "Failed to load projects" ) ;
}
const results = await response . json ( ) ;
if ( results . data ) {
this . projects = results . data ;
}
} catch ( error ) {
logger . error ( "Error loading projects:" , error ) ;
this . $notify (
{
group : "alert" ,
type : "danger" ,
title : "Error" ,
text : "Failed to load projects" ,
} ,
3000 ,
) ;
}
}
selectProject ( project : PlanData ) {
this . giver = {
did : project . handleId ,
name : project . name ,
image : project . image ,
handleId : project . handleId
} ;
this . receiver = {
did : this . activeDid ,
name : "You"
} ;
this . currentStep = 2 ;
}
}
< / script >