Trent Larson
3 weeks ago
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