7 changed files with 356 additions and 76 deletions
			
			
		| @ -0,0 +1,151 @@ | |||||
|  | <template> | ||||
|  |   <QuickNav selected="Discover" /> | ||||
|  |   <TopMessage /> | ||||
|  | 
 | ||||
|  |   <!-- CONTENT --> | ||||
|  |   <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto"> | ||||
|  |     <h1 id="ViewHeading" class="text-4xl text-center font-light"> | ||||
|  |       Individual Profile | ||||
|  |     </h1> | ||||
|  | 
 | ||||
|  |     <!-- Loading Animation --> | ||||
|  |     <div | ||||
|  |       class="fixed left-6 mt-16 text-center text-4xl leading-none bg-slate-400 text-white w-14 py-2.5 rounded-full" | ||||
|  |       v-if="isLoading" | ||||
|  |     > | ||||
|  |       <fa icon="spinner" class="fa-spin-pulse"></fa> | ||||
|  |     </div> | ||||
|  | 
 | ||||
|  |     <div v-else-if="profile"> | ||||
|  |       <!-- Profile Info --> | ||||
|  |       <div class="mt-8"> | ||||
|  |         <div class="text-sm"> | ||||
|  |           <fa icon="user" class="fa-fw text-slate-400"></fa> | ||||
|  |           {{ didInfo(profile.issuerDid, activeDid, allMyDids, allContacts) }} | ||||
|  |         </div> | ||||
|  |         <p v-if="profile.description" class="mt-4 text-slate-600"> | ||||
|  |           {{ profile.description }} | ||||
|  |         </p> | ||||
|  |       </div> | ||||
|  | 
 | ||||
|  |       <!-- Map --> | ||||
|  |       <div v-if="profile?.locLat && profile?.locLon" 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" | ||||
|  |           > | ||||
|  |             <l-tile-layer | ||||
|  |               url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" | ||||
|  |               layer-type="base" | ||||
|  |               name="OpenStreetMap" | ||||
|  |             /> | ||||
|  |             <l-marker :lat-lng="[profile.locLat, profile.locLon]"> | ||||
|  |               <l-popup>{{ | ||||
|  |                 didInfo(profile.issuerDid, activeDid, allMyDids, allContacts) | ||||
|  |               }}</l-popup> | ||||
|  |             </l-marker> | ||||
|  |           </l-map> | ||||
|  |         </div> | ||||
|  |       </div> | ||||
|  |     </div> | ||||
|  | 
 | ||||
|  |     <div v-else class="text-center mt-8"> | ||||
|  |       <p class="text-lg text-slate-500">Profile not found.</p> | ||||
|  |     </div> | ||||
|  |   </section> | ||||
|  | </template> | ||||
|  | 
 | ||||
|  | <script lang="ts"> | ||||
|  | import "leaflet/dist/leaflet.css"; | ||||
|  | import { Component, Vue } from "vue-facing-decorator"; | ||||
|  | import { LMap, LTileLayer, LMarker, LPopup } from "@vue-leaflet/vue-leaflet"; | ||||
|  | import { Router, RouteLocationNormalizedLoaded } from "vue-router"; | ||||
|  | 
 | ||||
|  | import QuickNav from "@/components/QuickNav.vue"; | ||||
|  | import TopMessage from "@/components/TopMessage.vue"; | ||||
|  | import { DEFAULT_PARTNER_API_SERVER, NotificationIface } from "@/constants/app"; | ||||
|  | import { db } from "@/db/index"; | ||||
|  | import { Contact } from "@/db/tables/contacts"; | ||||
|  | import { didInfo, getHeaders } from "@/libs/endorserServer"; | ||||
|  | import { UserProfile } from "@/libs/partnerServer"; | ||||
|  | import { retrieveAccountDids } from "@/libs/util"; | ||||
|  | 
 | ||||
|  | @Component({ | ||||
|  |   components: { | ||||
|  |     LMap, | ||||
|  |     LMarker, | ||||
|  |     LPopup, | ||||
|  |     LTileLayer, | ||||
|  |     QuickNav, | ||||
|  |     TopMessage, | ||||
|  |   }, | ||||
|  | }) | ||||
|  | export default class UserProfileView extends Vue { | ||||
|  |   $notify!: (notification: NotificationIface, timeout?: number) => void; | ||||
|  |   $router!: Router; | ||||
|  |   $route!: RouteLocationNormalizedLoaded; | ||||
|  | 
 | ||||
|  |   activeDid = ""; | ||||
|  |   allContacts: Array<Contact> = []; | ||||
|  |   allMyDids: Array<string> = []; | ||||
|  |   isLoading = true; | ||||
|  |   partnerApiServer = DEFAULT_PARTNER_API_SERVER; | ||||
|  |   profile: UserProfile | null = null; | ||||
|  | 
 | ||||
|  |   // make this function available to the Vue template | ||||
|  |   didInfo = didInfo; | ||||
|  | 
 | ||||
|  |   async mounted() { | ||||
|  |     const settings = await db.settings.toArray(); | ||||
|  |     this.activeDid = settings[0]?.activeDid || ""; | ||||
|  |     this.partnerApiServer = | ||||
|  |       settings[0]?.partnerApiServer || this.partnerApiServer; | ||||
|  | 
 | ||||
|  |     this.allContacts = await db.contacts.toArray(); | ||||
|  |     this.allMyDids = await retrieveAccountDids(); | ||||
|  | 
 | ||||
|  |     await this.loadProfile(); | ||||
|  |   } | ||||
|  | 
 | ||||
|  |   async loadProfile() { | ||||
|  |     const profileId: string = this.$route.params.id as string; | ||||
|  |     if (!profileId) { | ||||
|  |       this.isLoading = false; | ||||
|  |       return; | ||||
|  |     } | ||||
|  | 
 | ||||
|  |     try { | ||||
|  |       const response = await fetch( | ||||
|  |         `${this.partnerApiServer}/api/partner/userProfile/${encodeURIComponent(profileId)}`, | ||||
|  |         { | ||||
|  |           method: "GET", | ||||
|  |           headers: await getHeaders(this.activeDid), | ||||
|  |         }, | ||||
|  |       ); | ||||
|  | 
 | ||||
|  |       if (response.status === 200) { | ||||
|  |         const result = await response.json(); | ||||
|  |         this.profile = result.data; | ||||
|  |       } else { | ||||
|  |         throw new Error("Failed to load profile"); | ||||
|  |       } | ||||
|  |     } catch (error) { | ||||
|  |       console.error("Error loading profile:", error); | ||||
|  |       this.$notify( | ||||
|  |         { | ||||
|  |           group: "alert", | ||||
|  |           type: "danger", | ||||
|  |           title: "Error", | ||||
|  |           text: "There was a problem loading the profile.", | ||||
|  |         }, | ||||
|  |         5000, | ||||
|  |       ); | ||||
|  |     } finally { | ||||
|  |       this.isLoading = false; | ||||
|  |     } | ||||
|  |   } | ||||
|  | } | ||||
|  | </script> | ||||
					Loading…
					
					
				
		Reference in new issue