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[] = [];
|
allProjects: PlanData[] = [];
|
||||||
allContacts: Contact[] = [];
|
allContacts: Contact[] = [];
|
||||||
allMyDids: string[] = [];
|
allMyDids: string[] = [];
|
||||||
|
selectedProjectData: PlanData | null = null;
|
||||||
get minDateTime() {
|
get minDateTime() {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
now.setMinutes(now.getMinutes() + 5); // Set minimum 5 minutes in the future
|
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.loadProjects();
|
||||||
|
|
||||||
await this.fetchCurrentMeeting();
|
await this.fetchCurrentMeeting();
|
||||||
|
|
||||||
|
// Ensure selected project is loaded if projectLink exists
|
||||||
|
await this.ensureSelectedProjectLoaded();
|
||||||
|
|
||||||
this.isLoading = false;
|
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() {
|
async createMeeting() {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
|
||||||
@@ -652,7 +716,7 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startEditing() {
|
async startEditing() {
|
||||||
// Populate form with existing meeting data
|
// Populate form with existing meeting data
|
||||||
if (this.currentMeeting) {
|
if (this.currentMeeting) {
|
||||||
const localExpiresAt = new Date(this.currentMeeting.expiresAt);
|
const localExpiresAt = new Date(this.currentMeeting.expiresAt);
|
||||||
@@ -663,6 +727,10 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
password: this.currentMeeting.password || "",
|
password: this.currentMeeting.password || "",
|
||||||
projectLink: this.currentMeeting.projectLink || "",
|
projectLink: this.currentMeeting.projectLink || "",
|
||||||
};
|
};
|
||||||
|
// Ensure selected project is loaded if projectLink exists
|
||||||
|
if (this.currentMeeting.projectLink) {
|
||||||
|
await this.ensureSelectedProjectLoaded();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.$logError(
|
this.$logError(
|
||||||
"There is no current meeting to edit. We should never get here.",
|
"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
|
// Reset form data
|
||||||
this.newOrUpdatedMeetingInputs = null;
|
this.newOrUpdatedMeetingInputs = null;
|
||||||
|
// Restore selected project from currentMeeting if it exists
|
||||||
|
if (this.currentMeeting?.projectLink) {
|
||||||
|
await this.ensureSelectedProjectLoaded();
|
||||||
|
} else {
|
||||||
|
this.selectedProjectData = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateMeeting() {
|
async updateMeeting() {
|
||||||
@@ -865,17 +939,10 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Computed property for selected project
|
* 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 {
|
get selectedProject(): PlanData | null {
|
||||||
if (!this.newOrUpdatedMeetingInputs?.projectLink) {
|
return this.selectedProjectData;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
this.allProjects.find(
|
|
||||||
(p) => p.handleId === this.newOrUpdatedMeetingInputs?.projectLink,
|
|
||||||
) || null
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -905,6 +972,9 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
* Handle project assignment from dialog
|
* Handle project assignment from dialog
|
||||||
*/
|
*/
|
||||||
handleProjectLinkAssigned(project: PlanData): void {
|
handleProjectLinkAssigned(project: PlanData): void {
|
||||||
|
// Store the selected project directly
|
||||||
|
this.selectedProjectData = project;
|
||||||
|
|
||||||
if (this.newOrUpdatedMeetingInputs) {
|
if (this.newOrUpdatedMeetingInputs) {
|
||||||
this.newOrUpdatedMeetingInputs.projectLink = project.handleId;
|
this.newOrUpdatedMeetingInputs.projectLink = project.handleId;
|
||||||
}
|
}
|
||||||
@@ -914,6 +984,7 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
* Unset the project link and revert to initial state
|
* Unset the project link and revert to initial state
|
||||||
*/
|
*/
|
||||||
unsetProjectLink(): void {
|
unsetProjectLink(): void {
|
||||||
|
this.selectedProjectData = null;
|
||||||
if (this.newOrUpdatedMeetingInputs) {
|
if (this.newOrUpdatedMeetingInputs) {
|
||||||
this.newOrUpdatedMeetingInputs.projectLink = "";
|
this.newOrUpdatedMeetingInputs.projectLink = "";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user