Introduce local fallback for book creation and improve error handling
- Added support for creating books locally when the cloud limit is reached. - Enhanced error handling in `AddNewBookForm` with `ApiError` and fallback logic for local book creation. - Implemented `BookTypeLimit` to manage type-specific book limits with visual indicators in `BookList`. - Refactored `TombstoneRecord` to standardize naming conventions for better API compatibility. - Updated `useSyncSeries` and `useSyncBooks` to handle empty tombstones gracefully. - Updated locales with new translations for fallback and error messaging.
This commit is contained in:
@@ -13,10 +13,20 @@ interface ApiRequestConfig {
|
||||
contentType?: ContentType;
|
||||
}
|
||||
|
||||
export class ApiError extends Error {
|
||||
statusCode: number;
|
||||
constructor(message: string, statusCode: number) {
|
||||
super(message);
|
||||
this.statusCode = statusCode;
|
||||
this.name = 'ApiError';
|
||||
}
|
||||
}
|
||||
|
||||
function handleApiError(error: unknown): never {
|
||||
if (axios.isAxiosError(error)) {
|
||||
const serverMessage: string = error.response?.data?.message || error.response?.data || error.message;
|
||||
throw new Error(serverMessage);
|
||||
const statusCode: number = error.response?.status ?? 500;
|
||||
throw new ApiError(serverMessage, statusCode);
|
||||
} else if (error instanceof Error) {
|
||||
throw new Error(error.message);
|
||||
}
|
||||
|
||||
@@ -718,7 +718,10 @@
|
||||
"titleTooShort": "Title is too short. Minimum 2 characters required.",
|
||||
"titleTooLong": "Title is too long. Maximum 50 characters allowed.",
|
||||
"typeMissing": "Select a genre.",
|
||||
"addingBook": "An error occurred while adding the book."
|
||||
"addingBook": "An error occurred while adding the book.",
|
||||
"limitReached": "You have reached the book limit for this type on the cloud.",
|
||||
"saveLocally": "Save locally",
|
||||
"localFallbackDescription": "You can still save this book locally on your device."
|
||||
},
|
||||
"bookTypeHint": {
|
||||
"title": "Type of work",
|
||||
|
||||
@@ -717,7 +717,10 @@
|
||||
"titleTooShort": "Le titre est trop court. Minimum 2 caractères requis",
|
||||
"titleTooLong": "Le titre est trop long. Maximum 50 caractères autorisés",
|
||||
"typeMissing": "Sélectionner un genre.",
|
||||
"addingBook": "Une erreur est survenue lors de l'ajout du livre."
|
||||
"addingBook": "Une erreur est survenue lors de l'ajout du livre.",
|
||||
"limitReached": "Vous avez atteint la limite de livres pour ce type sur le cloud.",
|
||||
"saveLocally": "Sauvegarder localement",
|
||||
"localFallbackDescription": "Vous pouvez tout de même enregistrer ce livre localement sur votre appareil."
|
||||
},
|
||||
"bookTypeHint": {
|
||||
"title": "Type d'oeuvre",
|
||||
|
||||
@@ -44,10 +44,10 @@ export interface SyncCheckResult {
|
||||
}
|
||||
|
||||
export interface TombstoneRecord {
|
||||
tableName: string;
|
||||
entityId: string;
|
||||
bookId: string | null;
|
||||
deletedAt: number;
|
||||
table_name: string;
|
||||
entity_id: string;
|
||||
book_id: string | null;
|
||||
deleted_at: number;
|
||||
}
|
||||
|
||||
// ─── User & Auth ───────────────────────────────────────────
|
||||
|
||||
@@ -106,3 +106,8 @@ export interface BookTags {
|
||||
objects: Tag[];
|
||||
worldElements: Tag[];
|
||||
}
|
||||
|
||||
export interface BookTypeLimit {
|
||||
current: number;
|
||||
max: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user