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