feat(nextjs): Proper api error handling
This commit is contained in:
parent
1ecd5c164b
commit
d7c9858365
10 changed files with 219 additions and 240 deletions
|
|
@ -12,7 +12,7 @@ import { Skeleton } from "@/components/ui/skeleton";
|
|||
import { Button } from "@/components/ui/button";
|
||||
import { PresentationGenerationApi } from "../services/api/presentation-generation";
|
||||
import { getStaticFileUrl } from "../utils/others";
|
||||
|
||||
import { toast } from "sonner";
|
||||
interface IconsEditorProps {
|
||||
icon_prompt?: string[] | null;
|
||||
onClose?: () => void;
|
||||
|
|
@ -53,8 +53,9 @@ const IconsEditor = ({
|
|||
limit: 40,
|
||||
});
|
||||
setIcons(data);
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
console.error("Error fetching icons:", error);
|
||||
toast.error(error.message || "Failed to fetch icons. Please try again.");
|
||||
setIcons([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
|
|
|
|||
|
|
@ -98,10 +98,10 @@ const ImageEditor = ({
|
|||
try {
|
||||
const response = await PresentationGenerationApi.getPreviousGeneratedImages();
|
||||
setPreviousGeneratedImages(response);
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
toast.error("Failed to get previous generated images. Please try again.");
|
||||
console.error("error in getting previous generated images", error);
|
||||
setError("Failed to get previous generated images. Please try again.");
|
||||
setError(error.message || "Failed to get previous generated images. Please try again.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -218,9 +218,9 @@ const ImageEditor = ({
|
|||
});
|
||||
|
||||
setPreviewImages(response);
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
console.error("Error in image generation", err);
|
||||
setError("Failed to generate image. Please try again.");
|
||||
setError(err.message || "Failed to generate image. Please try again.");
|
||||
} finally {
|
||||
setIsGenerating(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,11 +149,13 @@ const DocumentsPreviewPage: React.FC = () => {
|
|||
|
||||
dispatch(setPresentationId(createResponse.id));
|
||||
router.push("/outline");
|
||||
} catch (error) {
|
||||
console.error("Error in presentation creation:", error);
|
||||
toast.error("Error in presentation creation. Please try again.");
|
||||
} catch (error: any) {
|
||||
console.error("Error in radar presentation creation:", error);
|
||||
toast.error('Error', {
|
||||
description: error.message || "Error in radar presentation creation.",
|
||||
});
|
||||
setShowLoading({
|
||||
message: "Error in presentation creation.",
|
||||
message: "Error in radar presentation creation.",
|
||||
show: true,
|
||||
duration: 10,
|
||||
progress: false,
|
||||
|
|
|
|||
|
|
@ -86,10 +86,10 @@ export const usePresentationGeneration = (
|
|||
dispatch(clearPresentationData());
|
||||
router.push(`/presentation?id=${presentationId}&stream=true`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error in data generation", error);
|
||||
} catch (error: any) {
|
||||
console.error('Error In Presentation Generation(prepare).', error);
|
||||
toast.error("Generation Error", {
|
||||
description: "Failed to generate presentation. Please try again.",
|
||||
description: error.message || "Error In Presentation Generation(prepare).",
|
||||
});
|
||||
} finally {
|
||||
setLoadingState(DEFAULT_LOADING_STATE);
|
||||
|
|
|
|||
|
|
@ -60,9 +60,11 @@ const SlideContent = ({
|
|||
dispatch(updateSlide({ index: slide.index, slide: response }));
|
||||
toast.success("Slide updated successfully");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating slide:", error);
|
||||
toast.error("Failed to update slide. Please try again.");
|
||||
} catch (error: any) {
|
||||
console.error("Error in slide editing:", error);
|
||||
toast.error("Error in slide editing.", {
|
||||
description: error.message || "Error in slide editing.",
|
||||
});
|
||||
} finally {
|
||||
setIsUpdating(false);
|
||||
}
|
||||
|
|
@ -70,8 +72,11 @@ const SlideContent = ({
|
|||
const onDeleteSlide = async () => {
|
||||
try {
|
||||
dispatch(deletePresentationSlide(slide.index));
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
console.error("Error deleting slide:", error);
|
||||
toast.error("Error deleting slide.", {
|
||||
description: error.message || "Error deleting slide.",
|
||||
});
|
||||
}
|
||||
};
|
||||
// Scroll to the new slide when streaming and new slides are being generated
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ export const useAutoSave = ({
|
|||
|
||||
} catch (error) {
|
||||
console.error('❌ Auto-save failed:', error);
|
||||
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
// API Error Response Interface
|
||||
interface ApiErrorResponse {
|
||||
detail?: string;
|
||||
message?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
// API Response Handler Utility
|
||||
export class ApiResponseHandler {
|
||||
|
||||
static async handleResponse(response: Response, defaultErrorMessage: string): Promise<any> {
|
||||
// Handle successful responses
|
||||
if (response.ok) {
|
||||
// Handle 204 No Content responses
|
||||
if (response.status === 204) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to parse JSON response
|
||||
try {
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
// If JSON parsing fails but response is ok, return empty object
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// Handle error responses
|
||||
let errorMessage = defaultErrorMessage;
|
||||
|
||||
try {
|
||||
const errorData: ApiErrorResponse = await response.json();
|
||||
|
||||
// Extract error message in order of preference
|
||||
if (errorData.detail) {
|
||||
errorMessage = errorData.detail;
|
||||
} else if (errorData.message) {
|
||||
errorMessage = errorData.message;
|
||||
} else if (errorData.error) {
|
||||
errorMessage = errorData.error;
|
||||
}
|
||||
} catch (parseError) {
|
||||
// If JSON parsing fails, use status-based messages
|
||||
errorMessage = this.getStatusBasedErrorMessage(response.status, defaultErrorMessage);
|
||||
}
|
||||
|
||||
// Throw error with appropriate message
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
|
||||
static async handleResponseWithResult(response: Response, defaultErrorMessage: string): Promise<{success: boolean, message?: string}> {
|
||||
try {
|
||||
// Handle successful responses
|
||||
if (response.ok) {
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
// Handle error responses
|
||||
let errorMessage = defaultErrorMessage;
|
||||
|
||||
try {
|
||||
const errorData: ApiErrorResponse = await response.json();
|
||||
|
||||
// Extract error message in order of preference
|
||||
if (errorData.detail) {
|
||||
errorMessage = errorData.detail;
|
||||
} else if (errorData.message) {
|
||||
errorMessage = errorData.message;
|
||||
} else if (errorData.error) {
|
||||
errorMessage = errorData.error;
|
||||
}
|
||||
} catch (parseError) {
|
||||
// If JSON parsing fails, use status-based messages
|
||||
errorMessage = this.getStatusBasedErrorMessage(response.status, defaultErrorMessage);
|
||||
}
|
||||
|
||||
return {
|
||||
success: false,
|
||||
message: errorMessage,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
message: error instanceof Error ? error.message : defaultErrorMessage,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static getStatusBasedErrorMessage(status: number, defaultMessage: string): string {
|
||||
switch (status) {
|
||||
case 400:
|
||||
return "Bad request. Please check your input and try again.";
|
||||
case 401:
|
||||
return "Unauthorized. Please log in and try again.";
|
||||
case 403:
|
||||
return "Access forbidden. You don't have permission to perform this action.";
|
||||
case 404:
|
||||
return "Resource not found. The requested item may have been deleted or moved.";
|
||||
case 409:
|
||||
return "Conflict. The resource already exists or there's a conflict with the current state.";
|
||||
case 422:
|
||||
return "Validation error. Please check your input and try again.";
|
||||
case 429:
|
||||
return "Too many requests. Please wait a moment and try again.";
|
||||
case 500:
|
||||
return "Internal server error. Please try again later.";
|
||||
case 502:
|
||||
return "Bad gateway. The server is temporarily unavailable.";
|
||||
case 503:
|
||||
return "Service unavailable. Please try again later.";
|
||||
case 504:
|
||||
return "Gateway timeout. The request took too long to process.";
|
||||
default:
|
||||
return defaultMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export type { ApiErrorResponse };
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
import { getHeader, getHeaderForFormData } from "./header";
|
||||
import { IconSearch, ImageGenerate, ImageSearch, PreviousGeneratedImagesResponse } from "./params";
|
||||
import { ApiResponseHandler } from "./api-error-handler";
|
||||
|
||||
export class PresentationGenerationApi {
|
||||
static async uploadDoc(documents: File[]) {
|
||||
const formData = new FormData();
|
||||
|
|
@ -19,20 +21,13 @@ export class PresentationGenerationApi {
|
|||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Upload failed: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data;
|
||||
return await ApiResponseHandler.handleResponse(response, "Failed to upload documents");
|
||||
} catch (error) {
|
||||
console.error("Upload error:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static async decomposeDocuments(documentKeys: string[]) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
|
|
@ -46,28 +41,53 @@ export class PresentationGenerationApi {
|
|||
cache: "no-cache",
|
||||
}
|
||||
);
|
||||
if (response.status === 200) {
|
||||
const data = await response.json();
|
||||
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(`Failed to decompose files: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await ApiResponseHandler.handleResponse(response, "Failed to decompose documents");
|
||||
} catch (error) {
|
||||
console.error("Error in Decompose Files", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
static async createPresentation({
|
||||
prompt,
|
||||
n_slides,
|
||||
file_paths,
|
||||
language,
|
||||
}: {
|
||||
prompt: string;
|
||||
n_slides: number | null;
|
||||
file_paths?: string[];
|
||||
language: string | null;
|
||||
}) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/v1/ppt/presentation/create`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: getHeader(),
|
||||
body: JSON.stringify({
|
||||
prompt,
|
||||
n_slides,
|
||||
file_paths,
|
||||
language,
|
||||
}),
|
||||
cache: "no-cache",
|
||||
}
|
||||
);
|
||||
|
||||
return await ApiResponseHandler.handleResponse(response, "Failed to create presentation");
|
||||
} catch (error) {
|
||||
console.error("error in presentation creation", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static async editSlide(
|
||||
slide_id: string,
|
||||
|
||||
prompt: string
|
||||
) {
|
||||
try {
|
||||
|
||||
const response = await fetch(
|
||||
`/api/v1/ppt/slide/edit`,
|
||||
{
|
||||
|
|
@ -76,18 +96,12 @@ export class PresentationGenerationApi {
|
|||
body: JSON.stringify({
|
||||
id: slide_id,
|
||||
prompt,
|
||||
|
||||
}),
|
||||
cache: "no-cache",
|
||||
}
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to update slides");
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
return data;
|
||||
return await ApiResponseHandler.handleResponse(response, "Failed to update slide");
|
||||
} catch (error) {
|
||||
console.error("error in slide update", error);
|
||||
throw error;
|
||||
|
|
@ -105,15 +119,8 @@ export class PresentationGenerationApi {
|
|||
cache: "no-cache",
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(
|
||||
`Failed to update presentation content: ${response.statusText}`
|
||||
);
|
||||
}
|
||||
|
||||
return await ApiResponseHandler.handleResponse(response, "Failed to update presentation content");
|
||||
} catch (error) {
|
||||
console.error("error in presentation content update", error);
|
||||
throw error;
|
||||
|
|
@ -131,41 +138,17 @@ export class PresentationGenerationApi {
|
|||
cache: "no-cache",
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(`Failed to generate data: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await ApiResponseHandler.handleResponse(response, "Failed to prepare presentation");
|
||||
} catch (error) {
|
||||
console.error("error in data generation", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// IMAGE AND ICON SEARCH
|
||||
static async imageSearch(imageSearch: ImageSearch) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/v1/ppt/image/search`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: getHeader(),
|
||||
body: JSON.stringify(imageSearch),
|
||||
cache: "no-cache",
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(`Failed to search images: ${response.statusText}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("error in image search", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static async generateImage(imageGenerate: ImageGenerate) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
|
|
@ -176,20 +159,15 @@ export class PresentationGenerationApi {
|
|||
cache: "no-cache",
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(`Failed to generate images: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await ApiResponseHandler.handleResponse(response, "Failed to generate image");
|
||||
} catch (error) {
|
||||
console.error("error in image generation", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
static getPreviousGeneratedImages = async():Promise<PreviousGeneratedImagesResponse[]>=>{
|
||||
static getPreviousGeneratedImages = async (): Promise<PreviousGeneratedImagesResponse[]> => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/v1/ppt/images/generated`,
|
||||
|
|
@ -198,17 +176,14 @@ export class PresentationGenerationApi {
|
|||
headers: getHeader(),
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(`Failed to get previous generated images: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await ApiResponseHandler.handleResponse(response, "Failed to get previous generated images");
|
||||
} catch (error) {
|
||||
console.error("error in getting previous generated images", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
static async searchIcons(iconSearch: IconSearch) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
|
|
@ -219,41 +194,15 @@ export class PresentationGenerationApi {
|
|||
cache: "no-cache",
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(`Failed to search icons: ${response.statusText}`);
|
||||
}
|
||||
|
||||
return await ApiResponseHandler.handleResponse(response, "Failed to search icons");
|
||||
} catch (error) {
|
||||
console.error("error in icon search", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
static async updateDocuments(body: any) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/v1/ppt/document/update`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: getHeaderForFormData(),
|
||||
body: body,
|
||||
cache: "no-cache",
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(`Failed to update documents: ${response.statusText}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("error in document update", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// EXPORT PRESENTATION
|
||||
static async exportAsPPTX(presentationData: any) {
|
||||
|
|
@ -267,100 +216,13 @@ export class PresentationGenerationApi {
|
|||
cache: "no-cache",
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
return await response.json();
|
||||
} else {
|
||||
throw new Error(`Failed to export as pptx: ${response.statusText}`);
|
||||
}
|
||||
return await ApiResponseHandler.handleResponse(response, "Failed to export as PowerPoint");
|
||||
} catch (error) {
|
||||
console.error("error in pptx export", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
static async exportAsPDF(presentationData: any) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/v1/ppt/presentation/export_as_pdf`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: getHeader(),
|
||||
body: JSON.stringify(presentationData),
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(`Failed to export as pdf: ${response.statusText}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("error in pdf export", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
static async deleteSlide(presentation_id: string, slide_id: string) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/v1/ppt/slide/delete?presentation_id=${presentation_id}&slide_id=${slide_id}`,
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: getHeader(),
|
||||
cache: "no-cache",
|
||||
}
|
||||
);
|
||||
if (response.status === 204) {
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(`Failed to delete slide: ${response.statusText}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("error in slide deletion", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static async createPresentation({
|
||||
prompt,
|
||||
n_slides,
|
||||
file_paths,
|
||||
language,
|
||||
|
||||
|
||||
|
||||
}: {
|
||||
prompt: string;
|
||||
n_slides: number | null;
|
||||
file_paths?: string[];
|
||||
language: string | null;
|
||||
|
||||
}) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/v1/ppt/presentation/create`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: getHeader(),
|
||||
body: JSON.stringify({
|
||||
prompt,
|
||||
n_slides,
|
||||
file_paths,
|
||||
language,
|
||||
|
||||
|
||||
}),
|
||||
cache: "no-cache",
|
||||
}
|
||||
);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
return data;
|
||||
} else {
|
||||
throw new Error(`Failed to get questions: ${response.statusText}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("error in question generation", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -162,7 +162,7 @@ const UploadPage = () => {
|
|||
* Handles errors during presentation generation
|
||||
*/
|
||||
const handleGenerationError = (error: any) => {
|
||||
console.error("Error in presentation generation:", error);
|
||||
console.error("Error in upload page", error);
|
||||
setLoadingState({
|
||||
isLoading: false,
|
||||
message: "",
|
||||
|
|
@ -170,7 +170,7 @@ const UploadPage = () => {
|
|||
showProgress: false,
|
||||
});
|
||||
toast.error("Error", {
|
||||
description: "Failed to generate presentation. Please try again.",
|
||||
description: error.message || "Error in upload page.",
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import {
|
||||
getHeader,
|
||||
} from "@/app/(presentation-generator)/services/api/header";
|
||||
|
||||
|
||||
import { ApiResponseHandler } from "@/app/(presentation-generator)/services/api/api-error-handler";
|
||||
|
||||
export interface PresentationResponse {
|
||||
id: string;
|
||||
|
|
@ -33,38 +32,36 @@ export class DashboardApi {
|
|||
method: "GET",
|
||||
}
|
||||
);
|
||||
if (response.status === 200) {
|
||||
const data = await response.json();
|
||||
return data;
|
||||
} else if (response.status === 404) {
|
||||
|
||||
// Handle the special case where 404 means "no presentations found"
|
||||
if (response.status === 404) {
|
||||
console.log("No presentations found");
|
||||
return [];
|
||||
}
|
||||
return [];
|
||||
|
||||
return await ApiResponseHandler.handleResponse(response, "Failed to fetch presentations");
|
||||
} catch (error) {
|
||||
console.error("Error fetching presentations:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
static async getPresentation(id: string) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/v1/ppt/presentation/?id=${id}`,
|
||||
{
|
||||
method: "GET",
|
||||
|
||||
}
|
||||
);
|
||||
if (response.status === 200) {
|
||||
const data = await response.json();
|
||||
return data;
|
||||
}
|
||||
throw new Error("Presentation not found");
|
||||
|
||||
return await ApiResponseHandler.handleResponse(response, "Presentation not found");
|
||||
} catch (error) {
|
||||
console.error("Error fetching presentations:", error);
|
||||
console.error("Error fetching presentation:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
static async deletePresentation(presentation_id: string) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
|
|
@ -74,17 +71,8 @@ export class DashboardApi {
|
|||
headers: getHeader(),
|
||||
}
|
||||
);
|
||||
const data = await response.json();
|
||||
|
||||
if (response.status === 204) {
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
return {
|
||||
success: false,
|
||||
message: data.detail || "Failed to delete presentation",
|
||||
};
|
||||
return await ApiResponseHandler.handleResponseWithResult(response, "Failed to delete presentation");
|
||||
} catch (error) {
|
||||
console.error("Error deleting presentation:", error);
|
||||
return {
|
||||
|
|
@ -93,5 +81,4 @@ export class DashboardApi {
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue