diff --git a/src/services/ProfileService.ts b/src/services/ProfileService.ts index eb1f347b..bdb27f46 100644 --- a/src/services/ProfileService.ts +++ b/src/services/ProfileService.ts @@ -124,17 +124,55 @@ export class ProfileService { async deleteProfile(activeDid: string): Promise { try { const headers = await getHeaders(activeDid); - const response = await this.axios.delete( - `${this.partnerApiServer}/api/partner/userProfile`, - { headers }, - ); + logger.debug("Attempting to delete profile for DID:", activeDid); + logger.debug("Using partner API server:", this.partnerApiServer); + logger.debug("Request headers:", headers); + + const url = `${this.partnerApiServer}/api/partner/userProfile`; + logger.debug("DELETE request URL:", url); + + const response = await this.axios.delete(url, { headers }); - if (response.status === 200) { + if (response.status === 200 || response.status === 204) { + logger.debug("Profile deleted successfully"); return true; } else { - throw new Error(ACCOUNT_VIEW_CONSTANTS.ERRORS.PROFILE_NOT_DELETED); + logger.error("Unexpected response status when deleting profile:", { + status: response.status, + statusText: response.statusText, + data: response.data + }); + throw new Error(`Profile not deleted - HTTP ${response.status}: ${response.statusText}`); } } catch (error) { + if (this.isApiError(error) && error.response) { + const response = error.response as any; // Type assertion for error response + logger.error("API error deleting profile:", { + status: response.status, + statusText: response.statusText, + data: response.data, + url: (error as any).config?.url + }); + + // Handle specific HTTP status codes + if (response.status === 204) { + logger.debug("Profile deleted successfully (204 No Content)"); + return true; // 204 is success for DELETE operations + } else if (response.status === 404) { + logger.warn("Profile not found - may already be deleted"); + return true; // Consider this a success if profile doesn't exist + } else if (response.status === 400) { + logger.error("Bad request when deleting profile:", response.data); + throw new Error(`Profile deletion failed: ${response.data?.message || 'Bad request'}`); + } else if (response.status === 401) { + logger.error("Unauthorized to delete profile"); + throw new Error("You are not authorized to delete this profile"); + } else if (response.status === 403) { + logger.error("Forbidden to delete profile"); + throw new Error("You are not allowed to delete this profile"); + } + } + logger.error("Error deleting profile:", errorStringForLog(error)); handleApiError(error as AxiosError, "/api/partner/userProfile"); return false; diff --git a/src/views/AccountViewView.vue b/src/views/AccountViewView.vue index 81c2978e..1c38a8bb 100644 --- a/src/views/AccountViewView.vue +++ b/src/views/AccountViewView.vue @@ -174,14 +174,16 @@ :aria-busy="loadingProfile || savingProfile" > -
- - -
+
+ + + (Debug: {{ isMapReady ? 'Map Ready' : 'Map Loading' }}) +

The location you choose will be shared with the world until you remove @@ -194,6 +196,7 @@ class="!z-40 rounded-md" @click="onProfileMapClick" @ready="onMapReady" + @mounted="onMapMounted" > { + this.isMapReady = true; + logger.debug("Map ready set to true after mounted"); + }, 500); + } + + // Fallback method to handle map initialization failures + private handleMapInitFailure(): void { + logger.debug("Starting map initialization timeout (5 seconds)"); + setTimeout(() => { + if (!this.isMapReady) { + logger.warn("Map failed to initialize, forcing ready state"); + this.isMapReady = true; + } else { + logger.debug("Map initialized successfully, timeout not needed"); + } + }, 5000); // 5 second timeout } showProfileInfo(): void { @@ -1532,13 +1590,16 @@ export default class AccountViewView extends Vue { async saveProfile(): Promise { this.savingProfile = true; - const profileData: ProfileData = { - description: this.userProfileDesc, - latitude: this.userProfileLatitude, - longitude: this.userProfileLongitude, - includeLocation: this.includeUserProfileLocation, - }; try { + const profileData: ProfileData = { + description: this.userProfileDesc, + latitude: this.userProfileLatitude, + longitude: this.userProfileLongitude, + includeLocation: this.includeUserProfileLocation, + }; + + logger.debug("Saving profile data:", profileData); + const success = await this.profileService.saveProfile( this.activeDid, profileData, @@ -1549,6 +1610,7 @@ export default class AccountViewView extends Vue { this.notify.error(ACCOUNT_VIEW_CONSTANTS.ERRORS.PROFILE_SAVE_ERROR); } } catch (error) { + logger.error("Error saving profile:", error); this.notify.error(ACCOUNT_VIEW_CONSTANTS.ERRORS.PROFILE_SAVE_ERROR); } finally { this.savingProfile = false; @@ -1556,15 +1618,25 @@ export default class AccountViewView extends Vue { } toggleUserProfileLocation(): void { - const updated = this.profileService.toggleProfileLocation({ - description: this.userProfileDesc, - latitude: this.userProfileLatitude, - longitude: this.userProfileLongitude, - includeLocation: this.includeUserProfileLocation, - }); - this.userProfileLatitude = updated.latitude; - this.userProfileLongitude = updated.longitude; - this.includeUserProfileLocation = updated.includeLocation; + try { + const updated = this.profileService.toggleProfileLocation({ + description: this.userProfileDesc, + latitude: this.userProfileLatitude, + longitude: this.userProfileLongitude, + includeLocation: this.includeUserProfileLocation, + }); + this.userProfileLatitude = updated.latitude; + this.userProfileLongitude = updated.longitude; + this.includeUserProfileLocation = updated.includeLocation; + + // Reset map ready state when toggling location + if (!updated.includeLocation) { + this.isMapReady = false; + } + } catch (error) { + logger.error("Error in toggleUserProfileLocation:", error); + this.notify.error("Failed to toggle location setting"); + } } confirmEraseLatLong(): void { @@ -1592,6 +1664,7 @@ export default class AccountViewView extends Vue { async deleteProfile(): Promise { try { + logger.debug("Attempting to delete profile for DID:", this.activeDid); const success = await this.profileService.deleteProfile(this.activeDid); if (success) { this.notify.success(ACCOUNT_VIEW_CONSTANTS.SUCCESS.PROFILE_DELETED); @@ -1599,11 +1672,20 @@ export default class AccountViewView extends Vue { this.userProfileLatitude = 0; this.userProfileLongitude = 0; this.includeUserProfileLocation = false; + this.isMapReady = false; // Reset map state + logger.debug("Profile deleted successfully, UI state reset"); } else { this.notify.error(ACCOUNT_VIEW_CONSTANTS.ERRORS.PROFILE_DELETE_ERROR); } } catch (error) { - this.notify.error(ACCOUNT_VIEW_CONSTANTS.ERRORS.PROFILE_DELETE_ERROR); + logger.error("Error in deleteProfile component method:", error); + + // Show more specific error message if available + if (error instanceof Error) { + this.notify.error(error.message); + } else { + this.notify.error(ACCOUNT_VIEW_CONSTANTS.ERRORS.PROFILE_DELETE_ERROR); + } } } @@ -1616,8 +1698,43 @@ export default class AccountViewView extends Vue { } onProfileMapClick(event: LeafletMouseEvent) { - this.userProfileLatitude = event.latlng.lat; - this.userProfileLongitude = event.latlng.lng; + try { + if (event && event.latlng) { + this.userProfileLatitude = event.latlng.lat; + this.userProfileLongitude = event.latlng.lng; + } + } catch (error) { + logger.error("Error in onProfileMapClick:", error); + } + } + + onLocationCheckboxChange(): void { + try { + logger.debug("Location checkbox changed, new value:", this.includeUserProfileLocation); + if (!this.includeUserProfileLocation) { + // Location checkbox was unchecked, clean up map state + this.isMapReady = false; + this.userProfileLatitude = 0; + this.userProfileLongitude = 0; + logger.debug("Location unchecked, map state reset"); + } else { + // Location checkbox was checked, start map initialization timeout + this.isMapReady = false; + logger.debug("Location checked, starting map initialization timeout"); + + // Try to set map ready after a short delay to allow Vue to render + setTimeout(() => { + if (!this.isMapReady) { + logger.debug("Setting map ready after timeout"); + this.isMapReady = true; + } + }, 1000); // 1 second delay + + this.handleMapInitFailure(); + } + } catch (error) { + logger.error("Error in onLocationCheckboxChange:", error); + } } // IdentitySection event handlers