@ -32,7 +32,7 @@
< div class = "mt-8" >
< div class = "text-sm" >
< font -awesome icon = "user" class = "fa-fw text-slate-400" > < / f o n t - a w e s o m e >
{ { didInfo ( profile . issuerDid , activeDid , allMyDids , allContacts ) } }
{ { profileDisplayName } }
< button title = "Copy Link to Profile" @click ="onCopyLinkClick()" >
< font -awesome
icon = "link"
@ -46,46 +46,42 @@
< / div >
<!-- Map for first coordinates -- >
< div v-if ="profile?.locLat && profile?.locL on" class="mt-4" >
< div v-if ="hasFirstLocati on" class="mt-4" >
< h2 class = "text-lg font-semibold" > Location < / h2 >
< div class = "h-96 mt-2 w-full" >
< l -map
ref = "profileMap"
: center = "[profile.locLat, profile.locLon] "
: zoom = "12 "
: center = "firstLocationCoords "
: zoom = "mapZoom "
>
< l -tile -layer
url = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png "
: url = "tileLayerUrl "
layer - type = "base"
name = "OpenStreetMap"
/ >
< l -marker : lat -lng = " [ profile.locLat , profile.locLon ] " >
< l -popup > { {
didInfo ( profile . issuerDid , activeDid , allMyDids , allContacts )
} } < / l - p o p u p >
< l -marker :lat-lng ="firstLocationCoords" >
< l -popup > { { profileDisplayName } } < / l - p o p u p >
< / l - m a r k e r >
< / l - m a p >
< / div >
< / div >
<!-- Map for second coordinates -- >
< div v-if ="profile?.locLat2 && profile?.locLon2 " class="mt-4" >
< div v-if ="hasSecondLocation " class="mt-4" >
< h2 class = "text-lg font-semibold" > Second Location < / h2 >
< div class = "h-96 mt-2 w-full" >
< l -map
ref = "profileMap"
: center = "[profile.locLat2, profile.locLon2] "
: zoom = "12 "
: center = "secondLocationCoords "
: zoom = "mapZoom "
>
< l -tile -layer
url = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png "
: url = "tileLayerUrl "
layer - type = "base"
name = "OpenStreetMap"
/ >
< l -marker : lat -lng = " [ profile.locLat2 , profile.locLon2 ] " >
< l -popup > { {
didInfo ( profile . issuerDid , activeDid , allMyDids , allContacts )
} } < / l - p o p u p >
< l -marker :lat-lng ="secondLocationCoords" >
< l -popup > { { profileDisplayName } } < / l - p o p u p >
< / l - m a r k e r >
< / l - m a p >
< / div >
@ -111,15 +107,32 @@ import {
DEFAULT_PARTNER_API_SERVER ,
NotificationIface ,
} from "../constants/app" ;
import * as databaseUtil from "../db/databaseUtil" ;
import { Contact } from "../db/tables/contacts" ;
import { didInfo , getHeaders } from "../libs/endorserServer" ;
import { UserProfile } from "../libs/partnerServer" ;
import { retrieveAccountDids } from "../libs/util" ;
import { logger } from "../utils/logger" ;
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory" ;
import { Settings } from "@/db/tables/settings" ;
import { useClipboard } from "@vueuse/core" ;
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin" ;
import { createNotifyHelpers , TIMEOUTS } from "@/utils/notify" ;
import { NOTIFY_PROFILE_LOAD_ERROR } from "@/constants/notifications" ;
/ * *
* User Profile View Component
*
* Displays individual user profile information including :
* - Basic profile data and description
* - Location information with interactive maps
* - Profile link sharing functionality
*
* Features :
* - Profile data loading from partner API
* - Interactive maps for location visualization
* - Copy - to - clipboard functionality for profile links
* - Responsive design with loading states
*
* @ author Matthew Raymer
* /
@ Component ( {
components : {
LMap ,
@ -129,12 +142,15 @@ import { useClipboard } from "@vueuse/core";
QuickNav ,
TopMessage ,
} ,
mixins : [ PlatformServiceMixin ] ,
} )
export default class UserProfileView extends Vue {
$notify ! : ( notification : NotificationIface , timeout ? : number ) => void ;
$router ! : Router ;
$route ! : RouteLocationNormalizedLoaded ;
notify ! : ReturnType < typeof createNotifyHelpers > ;
activeDid = "" ;
allContacts : Array < Contact > = [ ] ;
allMyDids : Array < string > = [ ] ;
@ -145,29 +161,47 @@ export default class UserProfileView extends Vue {
/ / m a k e t h i s f u n c t i o n a v a i l a b l e t o t h e V u e t e m p l a t e
didInfo = didInfo ;
async mounted ( ) {
const platformService = PlatformServiceFactory . getInstance ( ) ;
const settingsQuery = await platformService . dbQuery (
"SELECT * FROM settings" ,
) ;
const settings = databaseUtil . mapQueryResultToValues (
settingsQuery ,
) as Settings [ ] ;
this . activeDid = settings [ 0 ] ? . activeDid || "" ;
this . partnerApiServer =
settings [ 0 ] ? . partnerApiServer || this . partnerApiServer ;
const contactQuery = await platformService . dbQuery (
"SELECT * FROM contacts" ,
) ;
this . allContacts = databaseUtil . mapQueryResultToValues (
contactQuery ,
) as unknown as Contact [ ] ;
this . allMyDids = await retrieveAccountDids ( ) ;
/ * *
* Initializes notification helpers
* /
created ( ) {
this . notify = createNotifyHelpers ( this . $notify ) ;
}
/ * *
* Component initialization
*
* Loads account settings , contacts , and profile data
* Uses PlatformServiceMixin for database operations
* /
async mounted ( ) {
await this . initializeSettings ( ) ;
await this . loadContacts ( ) ;
await this . loadProfile ( ) ;
}
/ * *
* Initializes account settings from database
* /
private async initializeSettings ( ) {
const settings = await this . $accountSettings ( ) ;
this . activeDid = settings . activeDid || "" ;
this . partnerApiServer = settings . partnerApiServer || this . partnerApiServer ;
}
/ * *
* Loads all contacts from database
* /
private async loadContacts ( ) {
this . allContacts = await this . $getAllContacts ( ) ;
this . allMyDids = await retrieveAccountDids ( ) ;
}
/ * *
* Loads user profile data from partner API
*
* Handles profile loading with error handling and loading states
* /
async loadProfile ( ) {
const profileId : string = this . $route . params . id as string ;
if ( ! profileId ) {
@ -196,35 +230,85 @@ export default class UserProfileView extends Vue {
}
} catch ( error ) {
logger . error ( "Error loading profile:" , error ) ;
this . $notify (
{
group : "alert" ,
type : "danger" ,
title : "Error" ,
text : "There was a problem loading the profile." ,
} ,
5000 ,
) ;
this . notify . error ( NOTIFY_PROFILE_LOAD_ERROR . message , TIMEOUTS . LONG ) ;
} finally {
this . isLoading = false ;
}
}
/ * *
* Copies profile link to clipboard
*
* Creates a deep link to the profile and copies it to the clipboard
* Shows success notification when completed
* /
onCopyLinkClick ( ) {
const deepLink = ` ${ APP_SERVER } /deep-link/user-profile/ ${ this . profile ? . rowId } ` ;
useClipboard ( )
. copy ( deepLink )
. then ( ( ) => {
this . $notify (
{
group : "alert" ,
type : "toast" ,
title : "Copied" ,
text : "A link to this profile was copied to the clipboard." ,
} ,
2000 ,
) ;
} ) ;
this . notify . copied ( "profile link" , TIMEOUTS . STANDARD ) ;
} ) ;
}
/ * *
* Computed properties for template logic streamlining
* /
/ * *
* Gets the display name for the profile using didInfo utility
* @ returns Formatted display name for the profile owner
* /
get profileDisplayName ( ) {
return this . didInfo ( this . profile ? . issuerDid , this . activeDid , this . allMyDids , this . allContacts ) ;
}
/ * *
* Checks if the profile has first location coordinates
* @ returns True if both latitude and longitude are available
* /
get hasFirstLocation ( ) {
return this . profile ? . locLat && this . profile ? . locLon ;
}
/ * *
* Gets the coordinate array for the first location
* @ returns Array of [ latitude , longitude ] for map center
* /
get firstLocationCoords ( ) {
return [ this . profile ? . locLat , this . profile ? . locLon ] ;
}
/ * *
* Checks if the profile has second location coordinates
* @ returns True if both latitude and longitude are available
* /
get hasSecondLocation ( ) {
return this . profile ? . locLat2 && this . profile ? . locLon2 ;
}
/ * *
* Gets the coordinate array for the second location
* @ returns Array of [ latitude , longitude ] for map center
* /
get secondLocationCoords ( ) {
return [ this . profile ? . locLat2 , this . profile ? . locLon2 ] ;
}
/ * *
* Standard map zoom level for profile location maps
* @ returns Default zoom level for location display
* /
get mapZoom ( ) {
return 12 ;
}
/ * *
* OpenStreetMap tile layer URL template
* @ returns URL template for map tile fetching
* /
get tileLayerUrl ( ) {
return "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" ;
}
}
< / script >