add onboarding pages for the list and members, and refine the setup

This commit is contained in:
2025-02-03 12:18:13 -07:00
parent 2a23587c3b
commit 5ff91186e2
7 changed files with 616 additions and 60 deletions

View File

@@ -0,0 +1,197 @@
<template>
<QuickNav selected="Contacts" />
<TopMessage />
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light mb-8">
Onboarding Meetings
</h1>
<!-- Loading State -->
<div v-if="isLoading" class="flex justify-center items-center py-8">
<fa icon="spinner" class="fa-spin-pulse" />
</div>
<!-- Meeting List -->
<div v-else class="space-y-4">
<div v-for="meeting in meetings" :key="meeting.groupId"
class="p-4 bg-white rounded-lg shadow hover:shadow-md transition-shadow cursor-pointer"
@click="promptPassword(meeting)">
<h2 class="text-xl font-medium">{{ meeting.name }}</h2>
<p class="text-sm text-gray-600">Group ID: {{ meeting.groupId }}</p>
</div>
<p v-if="meetings.length === 0" class="text-center text-gray-500 py-8">
No onboarding meetings available
</p>
</div>
<!-- Password Dialog -->
<div v-if="showPasswordDialog" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4">
<div class="bg-white rounded-lg p-6 max-w-sm w-full">
<h3 class="text-lg font-medium mb-4">Enter Meeting Password</h3>
<input
v-model="password"
type="text"
class="w-full px-3 py-2 border rounded-md mb-4"
placeholder="Enter password"
@keyup.enter="submitPassword"
/>
<div class="flex justify-end space-x-4">
<button
@click="cancelPasswordDialog"
class="px-4 py-2 bg-gray-200 rounded hover:bg-gray-300"
>
Cancel
</button>
<button
@click="submitPassword"
class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
>
Submit
</button>
</div>
</div>
</div>
</section>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-facing-decorator';
import QuickNav from '@/components/QuickNav.vue';
import TopMessage from '@/components/TopMessage.vue';
import { logConsoleAndDb, retrieveSettingsForActiveAccount } from '@/db/index';
import { errorStringForLog, getHeaders, serverMessageForUser } from '@/libs/endorserServer';
import { encryptMessage } from '@/libs/crypto';
interface Meeting {
name: string;
groupId: number;
}
@Component({
components: {
QuickNav,
TopMessage,
},
})
export default class OnboardMeetingListView extends Vue {
$notify!: (notification: { group: string; type: string; title: string; text: string }, timeout?: number) => void;
meetings: Meeting[] = [];
isLoading = false;
showPasswordDialog = false;
password = '';
selectedMeeting: Meeting | null = null;
activeDid = '';
apiServer = '';
firstName = '';
async created() {
const settings = await retrieveSettingsForActiveAccount();
this.activeDid = settings.activeDid || '';
this.apiServer = settings.apiServer || '';
this.firstName = settings.firstName || '';
await this.fetchMeetings();
}
async fetchMeetings() {
this.isLoading = true;
try {
const headers = await getHeaders(this.activeDid);
const response = await this.axios.get(
this.apiServer + '/api/partner/groupsOnboarding',
{ headers }
);
if (response.data && response.data.data) {
this.meetings = response.data.data;
}
} catch (error) {
logConsoleAndDb('Error fetching meetings: ' + errorStringForLog(error), true);
this.$notify(
{
group: 'alert',
type: 'danger',
title: 'Error',
text: serverMessageForUser(error) || 'Failed to fetch meetings.',
},
5000
);
} finally {
this.isLoading = false;
}
}
promptPassword(meeting: Meeting) {
this.password = '';
this.selectedMeeting = meeting;
this.showPasswordDialog = true;
}
cancelPasswordDialog() {
this.password = '';
this.selectedMeeting = null;
this.showPasswordDialog = false;
}
async submitPassword() {
if (!this.selectedMeeting) {
return;
}
try {
// Create member data object
const memberData = {
name: this.firstName,
did: this.activeDid
};
const memberDataString = JSON.stringify(memberData);
const encryptedMemberData = await encryptMessage(memberDataString, this.password);
// Get headers for authentication
const headers = await getHeaders(this.activeDid);
// Encrypt the member data
const postResult = await this.axios.post(
this.apiServer + '/api/partner/groupOnboardMember',
{
groupId: this.selectedMeeting.groupId,
content: encryptedMemberData
},
{ headers }
);
if (postResult.data && postResult.data.success) {
// Navigate to members view with password and groupId
this.$router.push({
name: 'onboard-meeting-members',
params: {
groupId: this.selectedMeeting.groupId.toString()
},
query: {
password: this.password,
memberId: postResult.data.memberId
}
});
this.cancelPasswordDialog();
} else {
throw { response: postResult };
}
} catch (error) {
logConsoleAndDb('Error joining meeting: ' + errorStringForLog(error), true);
this.$notify(
{
group: 'alert',
type: 'danger',
title: 'Error',
text: serverMessageForUser(error) || 'Failed to join meeting.',
},
5000
);
}
}
}
</script>