limits vlaiadtion adn keywrods forms
This commit is contained in:
@@ -101,6 +101,29 @@ const getAuthToken = (): string | null => {
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Extract user-friendly error message from API error
|
||||
* Removes technical prefixes like "Failed to save:", "Failed to load:", etc.
|
||||
* if the backend error message is already descriptive
|
||||
*/
|
||||
export function getUserFriendlyError(error: any, fallback: string = 'An error occurred. Please try again.'): string {
|
||||
const message = error?.message || error?.error || fallback;
|
||||
|
||||
// If the message already describes a limit or specific problem, use it directly
|
||||
if (message.includes('limit exceeded') ||
|
||||
message.includes('not found') ||
|
||||
message.includes('already exists') ||
|
||||
message.includes('invalid') ||
|
||||
message.includes('required') ||
|
||||
message.includes('permission') ||
|
||||
message.includes('upgrade')) {
|
||||
return message;
|
||||
}
|
||||
|
||||
// Otherwise return the message as-is
|
||||
return message;
|
||||
}
|
||||
|
||||
// Get refresh token from store - try Zustand store first, then localStorage as fallback
|
||||
const getRefreshToken = (): string | null => {
|
||||
try {
|
||||
@@ -376,9 +399,11 @@ export async function fetchAPI(endpoint: string, options?: RequestInit & { timeo
|
||||
});
|
||||
|
||||
// Attach error data to error object so it can be accessed in catch block
|
||||
const apiError = new Error(`API Error (${response.status}): ${errorType} - ${errorMessage}`);
|
||||
// Use clean user-friendly message without technical jargon
|
||||
const apiError = new Error(errorMessage);
|
||||
(apiError as any).response = errorData;
|
||||
(apiError as any).status = response.status;
|
||||
(apiError as any).errorType = errorType;
|
||||
throw apiError;
|
||||
}
|
||||
|
||||
@@ -493,7 +518,11 @@ export interface Keyword {
|
||||
}
|
||||
|
||||
export interface KeywordCreateData {
|
||||
seed_keyword_id: number;
|
||||
keyword?: string; // For creating new custom keywords
|
||||
volume?: number | null; // For custom keywords
|
||||
difficulty?: number | null; // For custom keywords
|
||||
intent?: string; // For custom keywords
|
||||
seed_keyword_id?: number; // For linking existing seed keywords (optional)
|
||||
volume_override?: number | null;
|
||||
difficulty_override?: number | null;
|
||||
cluster_id?: number | null;
|
||||
@@ -554,9 +583,27 @@ export async function fetchKeyword(id: number): Promise<Keyword> {
|
||||
}
|
||||
|
||||
export async function createKeyword(data: KeywordCreateData): Promise<Keyword> {
|
||||
// Transform frontend field names to backend field names
|
||||
const requestData: any = {
|
||||
...data,
|
||||
};
|
||||
|
||||
// If creating a custom keyword, map to backend field names
|
||||
if (data.keyword) {
|
||||
requestData.custom_keyword = data.keyword;
|
||||
requestData.custom_volume = data.volume;
|
||||
requestData.custom_difficulty = data.difficulty;
|
||||
requestData.custom_intent = data.intent || 'informational';
|
||||
// Remove the frontend-only fields
|
||||
delete requestData.keyword;
|
||||
delete requestData.volume;
|
||||
delete requestData.difficulty;
|
||||
delete requestData.intent;
|
||||
}
|
||||
|
||||
return fetchAPI('/v1/planner/keywords/', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
body: JSON.stringify(requestData),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1988,13 +2035,14 @@ export async function addSeedKeywordsToWorkflow(seedKeywordIds: number[], siteId
|
||||
|
||||
return { success: true, ...response } as any;
|
||||
} catch (error: any) {
|
||||
// Error responses are thrown by fetchAPI - return as failed result instead of re-throwing
|
||||
// This allows component to handle limit errors gracefully
|
||||
// Error responses are thrown by fetchAPI - return as failed result
|
||||
// Extract clean user-friendly message (error.message is already cleaned in fetchAPI)
|
||||
const userMessage = error.message || 'Failed to add keywords';
|
||||
return {
|
||||
success: false,
|
||||
created: 0,
|
||||
skipped: 0,
|
||||
errors: [error.message || 'Failed to add keywords']
|
||||
errors: [userMessage]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user