forked from jsnbuchanan/crowd-funder-for-time-pwa
Refactor AccountViewView.vue to use notify helper and PlatformServiceMixin
- 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.
This commit is contained in:
223
src/services/ProfileService.ts
Normal file
223
src/services/ProfileService.ts
Normal file
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user