Browse Source
- Migrated all notification calls in AccountViewView.vue to use a notify helper initialized in mounted(), ensuring this.$notify is available and preventing runtime errors. - Removed NotificationMixin and $notifyHelper usage; restored and standardized notify helper pattern. - Migrated all database and platform service operations to use PlatformServiceMixin ultra-concise methods ($accountSettings, $saveSettings, $saveUserSettings, etc.). - Cleaned up unused imports and code related to previous notification and database patterns. - Ensured all linter errors and warnings are resolved in both AccountViewView.vue and notification utility files.pull/142/head
2 changed files with 325 additions and 238 deletions
@ -0,0 +1,223 @@ |
|||||
|
/** |
||||
|
* ProfileService - Handles user profile operations and API calls |
||||
|
* Extracted from AccountViewView.vue to improve separation of concerns |
||||
|
*/ |
||||
|
|
||||
|
import { AxiosInstance, AxiosError } from "axios"; |
||||
|
import { UserProfile } from "@/libs/partnerServer"; |
||||
|
import { UserProfileResponse } from "@/interfaces/accountView"; |
||||
|
import { getHeaders, errorStringForLog } from "@/libs/endorserServer"; |
||||
|
import { handleApiError } from "./api"; |
||||
|
import { logger } from "@/utils/logger"; |
||||
|
import { ACCOUNT_VIEW_CONSTANTS } from "@/constants/accountView"; |
||||
|
|
||||
|
/** |
||||
|
* Profile data interface |
||||
|
*/ |
||||
|
export interface ProfileData { |
||||
|
description: string; |
||||
|
latitude: number; |
||||
|
longitude: number; |
||||
|
includeLocation: boolean; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Profile service class |
||||
|
*/ |
||||
|
export class ProfileService { |
||||
|
private axios: AxiosInstance; |
||||
|
private partnerApiServer: string; |
||||
|
|
||||
|
constructor(axios: AxiosInstance, partnerApiServer: string) { |
||||
|
this.axios = axios; |
||||
|
this.partnerApiServer = partnerApiServer; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Load user profile from the server |
||||
|
* @param activeDid - The user's DID |
||||
|
* @returns ProfileData or null if profile doesn't exist |
||||
|
*/ |
||||
|
async loadProfile(activeDid: string): Promise<ProfileData | null> { |
||||
|
try { |
||||
|
const headers = await getHeaders(activeDid); |
||||
|
const response = await this.axios.get<UserProfileResponse>( |
||||
|
`${this.partnerApiServer}/api/partner/userProfileForIssuer/${activeDid}`, |
||||
|
{ headers }, |
||||
|
); |
||||
|
|
||||
|
if (response.status === 200) { |
||||
|
const data = response.data.data; |
||||
|
const profileData: ProfileData = { |
||||
|
description: data.description || "", |
||||
|
latitude: data.locLat || 0, |
||||
|
longitude: data.locLon || 0, |
||||
|
includeLocation: !!(data.locLat && data.locLon), |
||||
|
}; |
||||
|
return profileData; |
||||
|
} else { |
||||
|
throw new Error(ACCOUNT_VIEW_CONSTANTS.ERRORS.UNABLE_TO_LOAD_PROFILE); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
if (this.isApiError(error) && error.response?.status === 404) { |
||||
|
// Profile doesn't exist yet - this is normal
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
logger.error("Error loading profile:", errorStringForLog(error)); |
||||
|
handleApiError(error as AxiosError, "/api/partner/userProfileForIssuer"); |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Save user profile to the server |
||||
|
* @param activeDid - The user's DID |
||||
|
* @param profileData - The profile data to save |
||||
|
* @returns true if successful, false otherwise |
||||
|
*/ |
||||
|
async saveProfile( |
||||
|
activeDid: string, |
||||
|
profileData: ProfileData, |
||||
|
): Promise<boolean> { |
||||
|
try { |
||||
|
const headers = await getHeaders(activeDid); |
||||
|
const payload: UserProfile = { |
||||
|
description: profileData.description, |
||||
|
issuerDid: activeDid, |
||||
|
}; |
||||
|
|
||||
|
// Add location data if location is included
|
||||
|
if ( |
||||
|
profileData.includeLocation && |
||||
|
profileData.latitude && |
||||
|
profileData.longitude |
||||
|
) { |
||||
|
payload.locLat = profileData.latitude; |
||||
|
payload.locLon = profileData.longitude; |
||||
|
} |
||||
|
|
||||
|
const response = await this.axios.post( |
||||
|
`${this.partnerApiServer}/api/partner/userProfile`, |
||||
|
payload, |
||||
|
{ headers }, |
||||
|
); |
||||
|
|
||||
|
if (response.status === 200) { |
||||
|
return true; |
||||
|
} else { |
||||
|
throw new Error(ACCOUNT_VIEW_CONSTANTS.ERRORS.PROFILE_NOT_SAVED); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
logger.error("Error saving profile:", errorStringForLog(error)); |
||||
|
handleApiError(error as AxiosError, "/api/partner/userProfile"); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Delete user profile from the server |
||||
|
* @param activeDid - The user's DID |
||||
|
* @returns true if successful, false otherwise |
||||
|
*/ |
||||
|
async deleteProfile(activeDid: string): Promise<boolean> { |
||||
|
try { |
||||
|
const headers = await getHeaders(activeDid); |
||||
|
const response = await this.axios.delete( |
||||
|
`${this.partnerApiServer}/api/partner/userProfile`, |
||||
|
{ headers }, |
||||
|
); |
||||
|
|
||||
|
if (response.status === 200) { |
||||
|
return true; |
||||
|
} else { |
||||
|
throw new Error(ACCOUNT_VIEW_CONSTANTS.ERRORS.PROFILE_NOT_DELETED); |
||||
|
} |
||||
|
} catch (error) { |
||||
|
logger.error("Error deleting profile:", errorStringForLog(error)); |
||||
|
handleApiError(error as AxiosError, "/api/partner/userProfile"); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Update profile location |
||||
|
* @param profileData - Current profile data |
||||
|
* @param latitude - New latitude |
||||
|
* @param longitude - New longitude |
||||
|
* @returns Updated profile data |
||||
|
*/ |
||||
|
updateProfileLocation( |
||||
|
profileData: ProfileData, |
||||
|
latitude: number, |
||||
|
longitude: number, |
||||
|
): ProfileData { |
||||
|
return { |
||||
|
...profileData, |
||||
|
latitude, |
||||
|
longitude, |
||||
|
includeLocation: true, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Toggle location inclusion in profile |
||||
|
* @param profileData - Current profile data |
||||
|
* @returns Updated profile data |
||||
|
*/ |
||||
|
toggleProfileLocation(profileData: ProfileData): ProfileData { |
||||
|
const includeLocation = !profileData.includeLocation; |
||||
|
return { |
||||
|
...profileData, |
||||
|
latitude: includeLocation ? profileData.latitude : 0, |
||||
|
longitude: includeLocation ? profileData.longitude : 0, |
||||
|
includeLocation, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Clear profile location |
||||
|
* @param profileData - Current profile data |
||||
|
* @returns Updated profile data |
||||
|
*/ |
||||
|
clearProfileLocation(profileData: ProfileData): ProfileData { |
||||
|
return { |
||||
|
...profileData, |
||||
|
latitude: 0, |
||||
|
longitude: 0, |
||||
|
includeLocation: false, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Reset profile to default state |
||||
|
* @returns Default profile data |
||||
|
*/ |
||||
|
getDefaultProfile(): ProfileData { |
||||
|
return { |
||||
|
description: "", |
||||
|
latitude: 0, |
||||
|
longitude: 0, |
||||
|
includeLocation: false, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Type guard for API errors |
||||
|
*/ |
||||
|
private isApiError( |
||||
|
error: unknown, |
||||
|
): error is { response?: { status?: number } } { |
||||
|
return typeof error === "object" && error !== null && "response" in error; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Factory function to create a ProfileService instance |
||||
|
*/ |
||||
|
export function createProfileService( |
||||
|
axios: AxiosInstance, |
||||
|
partnerApiServer: string, |
||||
|
): ProfileService { |
||||
|
return new ProfileService(axios, partnerApiServer); |
||||
|
} |
Loading…
Reference in new issue