diff --git a/src/frontend/apps/impress/src/api/fetchApi.ts b/src/frontend/apps/impress/src/api/fetchApi.ts index c1d2dac0..03fad1f6 100644 --- a/src/frontend/apps/impress/src/api/fetchApi.ts +++ b/src/frontend/apps/impress/src/api/fetchApi.ts @@ -1,34 +1,33 @@ import { baseApiUrl, useAuthStore } from '@/core'; -/** - * Retrieves the CSRF token from the document's cookies. - * - * @returns {string|null} The CSRF token if found in the cookies, or null if not present. - */ -function getCSRFToken() { - return document.cookie - .split(';') - .filter((cookie) => cookie.trim().startsWith('csrftoken=')) - .map((cookie) => cookie.split('=')[1]) - .pop(); +import { getCSRFToken } from './utils'; + +interface FetchAPIInit extends RequestInit { + withoutContentType?: boolean; } export const fetchAPI = async ( input: string, - init?: RequestInit, + init?: FetchAPIInit, apiVersion = '1.0', ) => { const apiUrl = `${baseApiUrl(apiVersion)}${input}`; const csrfToken = getCSRFToken(); + const headers = { + 'Content-Type': 'application/json', + ...init?.headers, + ...(csrfToken && { 'X-CSRFToken': csrfToken }), + }; + + if (init?.withoutContentType) { + delete headers?.['Content-Type' as keyof typeof headers]; + } + const response = await fetch(apiUrl, { ...init, credentials: 'include', - headers: { - ...init?.headers, - 'Content-Type': 'application/json', - ...(csrfToken && { 'X-CSRFToken': csrfToken }), - }, + headers, }); if (response.status === 401) { diff --git a/src/frontend/apps/impress/src/api/utils.ts b/src/frontend/apps/impress/src/api/utils.ts index 5a4370e1..8aea86ac 100644 --- a/src/frontend/apps/impress/src/api/utils.ts +++ b/src/frontend/apps/impress/src/api/utils.ts @@ -16,3 +16,14 @@ export const errorCauses = async (response: Response, data?: unknown) => { data, }; }; + +/** + * Retrieves the CSRF token from the document's cookies. + */ +export function getCSRFToken() { + return document.cookie + .split(';') + .filter((cookie) => cookie.trim().startsWith('csrftoken=')) + .map((cookie) => cookie.split('=')[1]) + .pop(); +} diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/api/useCreateDocUpload.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/api/useCreateDocUpload.tsx new file mode 100644 index 00000000..2d605d5d --- /dev/null +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/api/useCreateDocUpload.tsx @@ -0,0 +1,36 @@ +import { useMutation } from '@tanstack/react-query'; + +import { APIError, errorCauses, fetchAPI } from '@/api'; + +import { DocAttachment } from '../types'; + +interface CreateDocAttachment { + docId: string; + body: FormData; +} + +export const createDocAttachment = async ({ + docId, + body, +}: CreateDocAttachment): Promise => { + const response = await fetchAPI(`documents/${docId}/attachment-upload/`, { + method: 'POST', + body, + withoutContentType: true, + }); + + if (!response.ok) { + throw new APIError( + 'Failed to upload on the doc', + await errorCauses(response), + ); + } + + return response.json() as Promise; +}; + +export function useCreateDocAttachment() { + return useMutation({ + mutationFn: createDocAttachment, + }); +} diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/types.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/types.tsx new file mode 100644 index 00000000..4390a173 --- /dev/null +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/types.tsx @@ -0,0 +1,3 @@ +export interface DocAttachment { + file: string; +}