forked from trent_larson/crowd-funder-for-time-pwa
refactor(OnboardMeetingSetupView): fix selected project display after refresh
Refactor selectedProject computation to use separate storage instead of relying on allProjects array. This fixes a bug where the selected project wouldn't display after page refresh if it wasn't in the initial allProjects batch. Changes: - Add selectedProjectData property to store selected project independently - Simplify selectedProject computed to return selectedProjectData directly - Add fetchProjectByHandleId() to fetch single project by handleId - Add ensureSelectedProjectLoaded() to check allProjects first, then fetch - Update handleProjectLinkAssigned() to store directly in selectedProjectData - Remove band-aid solution of adding selected projects to allProjects array - Update startEditing() and cancelEditing() to ensure selected project loads - Call ensureSelectedProjectLoaded() in created() lifecycle hook This ensures the selected project always displays correctly, even when: - Selected from search results (not in allProjects) - Page is refreshed (allProjects reloads without selected project) - Project is in a later pagination batch
This commit is contained in:
@@ -421,6 +421,7 @@ export default class OnboardMeetingView extends Vue {
|
||||
allProjects: PlanData[] = [];
|
||||
allContacts: Contact[] = [];
|
||||
allMyDids: string[] = [];
|
||||
selectedProjectData: PlanData | null = null;
|
||||
get minDateTime() {
|
||||
const now = new Date();
|
||||
now.setMinutes(now.getMinutes() + 5); // Set minimum 5 minutes in the future
|
||||
@@ -447,6 +448,10 @@ export default class OnboardMeetingView extends Vue {
|
||||
await this.loadProjects();
|
||||
|
||||
await this.fetchCurrentMeeting();
|
||||
|
||||
// Ensure selected project is loaded if projectLink exists
|
||||
await this.ensureSelectedProjectLoaded();
|
||||
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
@@ -518,6 +523,65 @@ export default class OnboardMeetingView extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the selected project is loaded if projectLink exists
|
||||
* Checks allProjects first, then fetches if not found
|
||||
*/
|
||||
async ensureSelectedProjectLoaded(): Promise<void> {
|
||||
const projectLink =
|
||||
this.currentMeeting?.projectLink ||
|
||||
this.newOrUpdatedMeetingInputs?.projectLink;
|
||||
|
||||
if (!projectLink) {
|
||||
this.selectedProjectData = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if already loaded in allProjects
|
||||
const existingProject = this.allProjects.find(
|
||||
(p) => p.handleId === projectLink,
|
||||
);
|
||||
if (existingProject) {
|
||||
this.selectedProjectData = existingProject;
|
||||
return;
|
||||
}
|
||||
|
||||
// Not in allProjects, fetch it
|
||||
await this.fetchProjectByHandleId(projectLink);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a single project by handleId
|
||||
* @param handleId - The project handleId to fetch
|
||||
*/
|
||||
async fetchProjectByHandleId(handleId: string): Promise<void> {
|
||||
try {
|
||||
const headers = await getHeaders(this.activeDid);
|
||||
const url = `${this.apiServer}/api/v2/report/plans?handleId=${encodeURIComponent(handleId)}`;
|
||||
const resp = await this.axios.get(url, { headers });
|
||||
|
||||
if (resp.status === 200 && resp.data.data && resp.data.data.length > 0) {
|
||||
const project = resp.data.data[0];
|
||||
this.selectedProjectData = {
|
||||
name: project.name,
|
||||
description: project.description,
|
||||
image: project.image,
|
||||
handleId: project.handleId,
|
||||
issuerDid: project.issuerDid,
|
||||
rowId: project.rowId,
|
||||
};
|
||||
} else {
|
||||
this.selectedProjectData = null;
|
||||
}
|
||||
} catch (error) {
|
||||
this.$logAndConsole(
|
||||
"Error fetching project by handleId: " + errorStringForLog(error),
|
||||
true,
|
||||
);
|
||||
this.selectedProjectData = null;
|
||||
}
|
||||
}
|
||||
|
||||
async createMeeting() {
|
||||
this.isLoading = true;
|
||||
|
||||
@@ -652,7 +716,7 @@ export default class OnboardMeetingView extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
startEditing() {
|
||||
async startEditing() {
|
||||
// Populate form with existing meeting data
|
||||
if (this.currentMeeting) {
|
||||
const localExpiresAt = new Date(this.currentMeeting.expiresAt);
|
||||
@@ -663,6 +727,10 @@ export default class OnboardMeetingView extends Vue {
|
||||
password: this.currentMeeting.password || "",
|
||||
projectLink: this.currentMeeting.projectLink || "",
|
||||
};
|
||||
// Ensure selected project is loaded if projectLink exists
|
||||
if (this.currentMeeting.projectLink) {
|
||||
await this.ensureSelectedProjectLoaded();
|
||||
}
|
||||
} else {
|
||||
this.$logError(
|
||||
"There is no current meeting to edit. We should never get here.",
|
||||
@@ -670,9 +738,15 @@ export default class OnboardMeetingView extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
cancelEditing() {
|
||||
async cancelEditing() {
|
||||
// Reset form data
|
||||
this.newOrUpdatedMeetingInputs = null;
|
||||
// Restore selected project from currentMeeting if it exists
|
||||
if (this.currentMeeting?.projectLink) {
|
||||
await this.ensureSelectedProjectLoaded();
|
||||
} else {
|
||||
this.selectedProjectData = null;
|
||||
}
|
||||
}
|
||||
|
||||
async updateMeeting() {
|
||||
@@ -865,17 +939,10 @@ export default class OnboardMeetingView extends Vue {
|
||||
|
||||
/**
|
||||
* Computed property for selected project
|
||||
* Derives the project from projectLink by finding it in allProjects
|
||||
* Returns the separately stored selected project data
|
||||
*/
|
||||
get selectedProject(): PlanData | null {
|
||||
if (!this.newOrUpdatedMeetingInputs?.projectLink) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
this.allProjects.find(
|
||||
(p) => p.handleId === this.newOrUpdatedMeetingInputs?.projectLink,
|
||||
) || null
|
||||
);
|
||||
return this.selectedProjectData;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -905,6 +972,9 @@ export default class OnboardMeetingView extends Vue {
|
||||
* Handle project assignment from dialog
|
||||
*/
|
||||
handleProjectLinkAssigned(project: PlanData): void {
|
||||
// Store the selected project directly
|
||||
this.selectedProjectData = project;
|
||||
|
||||
if (this.newOrUpdatedMeetingInputs) {
|
||||
this.newOrUpdatedMeetingInputs.projectLink = project.handleId;
|
||||
}
|
||||
@@ -914,6 +984,7 @@ export default class OnboardMeetingView extends Vue {
|
||||
* Unset the project link and revert to initial state
|
||||
*/
|
||||
unsetProjectLink(): void {
|
||||
this.selectedProjectData = null;
|
||||
if (this.newOrUpdatedMeetingInputs) {
|
||||
this.newOrUpdatedMeetingInputs.projectLink = "";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user