mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-29 16:03:21 +00:00
feat: mise en place de la messagerie [#17]
This commit is contained in:
@ -3,7 +3,6 @@ import React, { useState, useEffect } from 'react';
|
||||
import Sidebar from '@/components/Sidebar';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Image from 'next/image';
|
||||
import {
|
||||
LayoutDashboard,
|
||||
FileText,
|
||||
@ -13,11 +12,8 @@ import {
|
||||
Calendar,
|
||||
Settings,
|
||||
LogOut,
|
||||
Menu,
|
||||
X,
|
||||
Mail,
|
||||
MessageSquare,
|
||||
} from 'lucide-react';
|
||||
import DropdownMenu from '@/components/DropdownMenu';
|
||||
|
||||
import Popup from '@/components/Popup';
|
||||
import {
|
||||
@ -86,7 +82,7 @@ export default function Layout({ children }) {
|
||||
id: 'messagerie',
|
||||
name: t('messagerie'),
|
||||
url: FE_ADMIN_MESSAGERIE_URL,
|
||||
icon: Mail,
|
||||
icon: MessageSquare,
|
||||
},
|
||||
settings: {
|
||||
id: 'settings',
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
'use client';
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import SidebarTabs from '@/components/SidebarTabs';
|
||||
import EmailSender from '@/components/Admin/EmailSender';
|
||||
import InstantMessaging from '@/components/Admin/InstantMessaging';
|
||||
@ -26,11 +26,8 @@ export default function MessageriePage({ csrfToken }) {
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full">
|
||||
<SidebarTabs
|
||||
tabs={tabs}
|
||||
onTabChange={(tabId) => logger.debug(`Onglet actif : ${tabId}`)}
|
||||
/>
|
||||
<div className="h-full flex flex-col p-0 m-0">
|
||||
<SidebarTabs tabs={tabs} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,31 +1,64 @@
|
||||
'use client';
|
||||
// src/components/Layout.js
|
||||
import React, { useState } from 'react';
|
||||
import ProfileSelector from '@/components/ProfileSelector';
|
||||
import { useRouter } from 'next/navigation'; // Ajout de l'importation
|
||||
import { MessageSquare, LogOut, Settings, Home } from 'lucide-react'; // Ajout de l'importation de l'icône Home
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import Sidebar from '@/components/Sidebar';
|
||||
import { useRouter, usePathname } from 'next/navigation';
|
||||
import { MessageSquare, Settings, Home, Menu } from 'lucide-react';
|
||||
import {
|
||||
FE_PARENTS_HOME_URL,
|
||||
FE_PARENTS_MESSAGERIE_URL,
|
||||
FE_PARENTS_SETTINGS_URL,
|
||||
} from '@/utils/Url'; // Ajout de l'importation de l'URL de la page d'accueil parent
|
||||
} from '@/utils/Url';
|
||||
import ProtectedRoute from '@/components/ProtectedRoute';
|
||||
import { disconnect } from '@/app/actions/authAction';
|
||||
import Popup from '@/components/Popup';
|
||||
import logger from '@/utils/logger';
|
||||
import { getRightStr, RIGHTS } from '@/utils/rights';
|
||||
import { RIGHTS } from '@/utils/rights';
|
||||
import { useEstablishment } from '@/context/EstablishmentContext';
|
||||
|
||||
import Footer from '@/components/Footer';
|
||||
|
||||
export default function Layout({ children }) {
|
||||
const router = useRouter(); // Définition de router
|
||||
const [messages, setMessages] = useState([]);
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const [isPopupVisible, setIsPopupVisible] = useState(false);
|
||||
const { profileRole, user, clearContext } = useEstablishment();
|
||||
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
||||
const { clearContext } = useEstablishment();
|
||||
const softwareName = 'N3WT School';
|
||||
const softwareVersion = `${process.env.NEXT_PUBLIC_APP_VERSION}`;
|
||||
|
||||
// Vérifier si on est sur la page messagerie
|
||||
const isMessagingPage = pathname?.includes('/messagerie');
|
||||
|
||||
// Configuration des éléments de la sidebar pour les parents
|
||||
const sidebarItems = [
|
||||
{
|
||||
id: 'home',
|
||||
name: 'Accueil',
|
||||
url: FE_PARENTS_HOME_URL,
|
||||
icon: Home,
|
||||
},
|
||||
{
|
||||
id: 'messagerie',
|
||||
name: 'Messagerie',
|
||||
url: FE_PARENTS_MESSAGERIE_URL,
|
||||
icon: MessageSquare,
|
||||
},
|
||||
{
|
||||
id: 'settings',
|
||||
name: 'Paramètres',
|
||||
url: FE_PARENTS_SETTINGS_URL,
|
||||
icon: Settings,
|
||||
},
|
||||
];
|
||||
|
||||
// Déterminer la page actuelle pour la sidebar
|
||||
const getCurrentPage = () => {
|
||||
if (pathname?.includes('/messagerie')) return 'messagerie';
|
||||
if (pathname?.includes('/settings')) return 'settings';
|
||||
return 'home';
|
||||
};
|
||||
|
||||
const currentPage = getCurrentPage();
|
||||
|
||||
const handleDisconnect = () => {
|
||||
setIsPopupVisible(true);
|
||||
};
|
||||
@ -35,52 +68,63 @@ export default function Layout({ children }) {
|
||||
disconnect();
|
||||
clearContext();
|
||||
};
|
||||
|
||||
const toggleSidebar = () => {
|
||||
setIsSidebarOpen(!isSidebarOpen);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// Fermer la sidebar quand on change de page sur mobile
|
||||
setIsSidebarOpen(false);
|
||||
}, [pathname]);
|
||||
|
||||
return (
|
||||
<ProtectedRoute requiredRight={RIGHTS.PARENT}>
|
||||
<div className="flex flex-col min-h-screen bg-gray-50">
|
||||
{/* Entête */}
|
||||
<header className="h-16 bg-white border-b border-gray-200 px-4 md:px-8 py-4 flex items-center justify-between fixed top-0 left-0 right-0 z-10">
|
||||
<div className="flex items-center space-x-2">
|
||||
{/* Suppression du menu profil parent */}
|
||||
{/* Bouton hamburger pour mobile */}
|
||||
<button
|
||||
onClick={toggleSidebar}
|
||||
className="fixed top-4 left-4 z-40 p-2 rounded-md bg-white shadow-lg border border-gray-200 md:hidden"
|
||||
>
|
||||
<Menu size={20} />
|
||||
</button>
|
||||
|
||||
<div className="text-lg md:text-xl p-2 font-semibold">Accueil</div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2 md:space-x-4">
|
||||
<button
|
||||
className="p-1 md:p-2 rounded-full hover:bg-gray-200"
|
||||
onClick={() => {
|
||||
router.push(FE_PARENTS_HOME_URL);
|
||||
}}
|
||||
>
|
||||
<Home className="h-5 w-5 md:h-6 md:w-6" />
|
||||
</button>
|
||||
<div className="relative">
|
||||
<button
|
||||
className="p-1 md:p-2 rounded-full hover:bg-gray-200"
|
||||
onClick={() => {
|
||||
router.push(FE_PARENTS_MESSAGERIE_URL);
|
||||
}}
|
||||
>
|
||||
<MessageSquare className="h-5 w-5 md:h-6 md:w-6" />
|
||||
</button>
|
||||
{messages.length > 0 && (
|
||||
<span className="absolute top-0 right-0 block h-2 w-2 rounded-full bg-emerald-600"></span>
|
||||
)}
|
||||
</div>
|
||||
<ProfileSelector className="w-64 border-b border-gray-200 " />
|
||||
{/* Suppression du DropdownMenu profil parent */}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{/* Content */}
|
||||
<div className="pt-16 md:pt-20 p-4 md:p-8 flex-1">
|
||||
{' '}
|
||||
{/* Ajout de flex-1 pour utiliser toute la hauteur disponible */}
|
||||
{children}
|
||||
</div>
|
||||
{/* Footer responsive */}
|
||||
<Footer softwareName={softwareName} softwareVersion={softwareVersion} />
|
||||
{/* Sidebar */}
|
||||
<div
|
||||
className={`absolute top-0 bottom-0 left-0 z-30 w-64 bg-white border-r border-gray-200 box-border ${
|
||||
isSidebarOpen ? 'block' : 'hidden md:block'
|
||||
}`}
|
||||
>
|
||||
<Sidebar
|
||||
currentPage={currentPage}
|
||||
items={sidebarItems}
|
||||
onCloseMobile={toggleSidebar}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Overlay for mobile */}
|
||||
{isSidebarOpen && (
|
||||
<div
|
||||
className="fixed inset-0 bg-black bg-opacity-50 z-20 md:hidden"
|
||||
onClick={toggleSidebar}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Main container */}
|
||||
<div
|
||||
className={`absolute overflow-auto bg-gradient-to-br from-emerald-50 via-sky-50 to-emerald-100 top-0 bottom-16 left-0 md:left-64 right-0 ${!isMessagingPage ? 'p-4 md:p-8' : ''}`}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
|
||||
{/* Footer */}
|
||||
<Footer softwareName={softwareName} softwareVersion={softwareVersion} />
|
||||
|
||||
<Popup
|
||||
isOpen={isPopupVisible}
|
||||
message="Êtes-vous sûr(e) de vouloir vous déconnecter ?"
|
||||
onConfirm={confirmDisconnect}
|
||||
onCancel={() => setIsPopupVisible(false)}
|
||||
/>
|
||||
</ProtectedRoute>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,15 +1,28 @@
|
||||
'use client';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import Chat from '@/components/Chat';
|
||||
|
||||
import React from 'react';
|
||||
import InstantChat from '@/components/Chat/InstantChat';
|
||||
import { useEstablishment } from '@/context/EstablishmentContext';
|
||||
|
||||
export default function MessageriePage() {
|
||||
const { user, selectedEstablishmentId } = useEstablishment();
|
||||
|
||||
if (!user) return <div>Chargement...</div>;
|
||||
if (!user?.user_id || !selectedEstablishmentId) {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-full w-full">
|
||||
<div className="text-center">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-gray-900 mx-auto mb-4"></div>
|
||||
<p className="text-gray-600">Chargement de la messagerie...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Chat userProfileId={user.id} establishmentId={selectedEstablishmentId} />
|
||||
<div className="h-full flex flex-col">
|
||||
<InstantChat
|
||||
userProfileId={user.user_id}
|
||||
establishmentId={selectedEstablishmentId}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
34
Front-End/src/app/actions/emailAction.js
Normal file
34
Front-End/src/app/actions/emailAction.js
Normal file
@ -0,0 +1,34 @@
|
||||
import {
|
||||
BE_GESTIONEMAIL_SEARCH_RECIPIENTS_URL,
|
||||
BE_GESTIONEMAIL_SEND_EMAIL_URL,
|
||||
} from '@/utils/Url';
|
||||
import { errorHandler, requestResponseHandler } from './actionsHandlers';
|
||||
import { getCsrfToken } from '@/utils/getCsrfToken';
|
||||
|
||||
// Recherche de destinataires pour email
|
||||
export const searchRecipients = (establishmentId, query) => {
|
||||
const url = `${BE_GESTIONEMAIL_SEARCH_RECIPIENTS_URL}/?establishment_id=${establishmentId}&q=${encodeURIComponent(query)}`;
|
||||
return fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
.catch(errorHandler);
|
||||
};
|
||||
// Envoyer un email
|
||||
export const sendEmail = async (messageData) => {
|
||||
const csrfToken = getCsrfToken();
|
||||
return fetch(BE_GESTIONEMAIL_SEND_EMAIL_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrfToken,
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(messageData),
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
.catch(errorHandler);
|
||||
};
|
||||
@ -1,67 +1,251 @@
|
||||
import {
|
||||
BE_GESTIONMESSAGERIE_CONVERSATIONS_URL,
|
||||
BE_GESTIONMESSAGERIE_CONVERSATION_MESSAGES_URL,
|
||||
BE_GESTIONMESSAGERIE_MARK_AS_READ_URL,
|
||||
BE_GESTIONMESSAGERIE_MESSAGES_URL,
|
||||
BE_GESTIONMESSAGERIE_SEND_MESSAGE_URL,
|
||||
BE_GESTIONMESSAGERIE_CREATE_CONVERSATION_URL,
|
||||
BE_GESTIONMESSAGERIE_SEARCH_RECIPIENTS_URL,
|
||||
BE_GESTIONMESSAGERIE_MARK_AS_READ_URL,
|
||||
BE_GESTIONMESSAGERIE_UPLOAD_FILE_URL,
|
||||
BE_GESTIONMESSAGERIE_DELETE_CONVERSATION_URL,
|
||||
} from '@/utils/Url';
|
||||
import { errorHandler, requestResponseHandler } from './actionsHandlers';
|
||||
import logger from '@/utils/logger';
|
||||
|
||||
export const fetchConversations = (profileId) => {
|
||||
return fetch(`${BE_GESTIONMESSAGERIE_CONVERSATIONS_URL}/${profileId}/`, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
.catch(errorHandler);
|
||||
// Helper pour construire les en-têtes avec CSRF
|
||||
const buildHeaders = (csrfToken) => {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
// Ajouter le token CSRF
|
||||
if (csrfToken) {
|
||||
headers['X-CSRFToken'] = csrfToken;
|
||||
}
|
||||
|
||||
return headers;
|
||||
};
|
||||
|
||||
export const fetchMessages = (conversationId) => {
|
||||
return fetch(
|
||||
`${BE_GESTIONMESSAGERIE_CONVERSATION_MESSAGES_URL}/${conversationId}/`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
/**
|
||||
* Récupère les conversations d'un utilisateur
|
||||
*/
|
||||
export const fetchConversations = async (userId, csrfToken) => {
|
||||
try {
|
||||
// Utiliser la nouvelle route avec user_id en paramètre d'URL
|
||||
const url = `${BE_GESTIONMESSAGERIE_CONVERSATIONS_URL}/user/${userId}/`;
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: buildHeaders(csrfToken),
|
||||
credentials: 'include',
|
||||
});
|
||||
return await requestResponseHandler(response);
|
||||
} catch (error) {
|
||||
logger.error('Erreur lors de la récupération des conversations:', error);
|
||||
return errorHandler(error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Récupère les messages d'une conversation
|
||||
*/
|
||||
export const fetchMessages = async (
|
||||
conversationId,
|
||||
page = 1,
|
||||
limit = 50,
|
||||
csrfToken,
|
||||
userId = null
|
||||
) => {
|
||||
try {
|
||||
// Utiliser la nouvelle URL avec conversation_id en paramètre d'URL
|
||||
let url = `${BE_GESTIONMESSAGERIE_CONVERSATIONS_URL}/${conversationId}/messages/?page=${page}&limit=${limit}`;
|
||||
|
||||
// Ajouter user_id si fourni pour calculer correctement is_read
|
||||
if (userId) {
|
||||
url += `&user_id=${userId}`;
|
||||
}
|
||||
)
|
||||
.then(requestResponseHandler)
|
||||
.catch(errorHandler);
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: buildHeaders(csrfToken),
|
||||
credentials: 'include',
|
||||
});
|
||||
return await requestResponseHandler(response);
|
||||
} catch (error) {
|
||||
logger.error('Erreur lors de la récupération des messages:', error);
|
||||
return errorHandler(error);
|
||||
}
|
||||
};
|
||||
|
||||
export const sendMessage = (data) => {
|
||||
return fetch(`${BE_GESTIONMESSAGERIE_MESSAGES_URL}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
.catch(errorHandler);
|
||||
/**
|
||||
* Envoie un message dans une conversation
|
||||
*/
|
||||
export const sendMessage = async (messageData, csrfToken) => {
|
||||
try {
|
||||
const response = await fetch(BE_GESTIONMESSAGERIE_SEND_MESSAGE_URL, {
|
||||
method: 'POST',
|
||||
headers: buildHeaders(csrfToken),
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(messageData),
|
||||
});
|
||||
return await requestResponseHandler(response);
|
||||
} catch (error) {
|
||||
logger.error("Erreur lors de l'envoi du message:", error);
|
||||
return errorHandler(error);
|
||||
}
|
||||
};
|
||||
|
||||
export const markAsRead = (conversationId, profileId) => {
|
||||
return fetch(`${BE_GESTIONMESSAGERIE_MARK_AS_READ_URL}/${conversationId}/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ profile_id: profileId }),
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
.catch(errorHandler);
|
||||
/**
|
||||
* Crée une nouvelle conversation
|
||||
*/
|
||||
export const createConversation = async (participantIds, csrfToken) => {
|
||||
try {
|
||||
const requestBody = {
|
||||
participant_ids: participantIds, // Le backend attend "participant_ids"
|
||||
conversation_type: 'private', // Spécifier le type de conversation
|
||||
name: '', // Le nom sera généré côté backend
|
||||
};
|
||||
|
||||
const response = await fetch(BE_GESTIONMESSAGERIE_CREATE_CONVERSATION_URL, {
|
||||
method: 'POST',
|
||||
headers: buildHeaders(csrfToken),
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(requestBody),
|
||||
});
|
||||
|
||||
return await requestResponseHandler(response);
|
||||
} catch (error) {
|
||||
logger.error('Erreur lors de la création de la conversation:', error);
|
||||
return errorHandler(error);
|
||||
}
|
||||
};
|
||||
|
||||
export const searchRecipients = (establishmentId, query) => {
|
||||
const url = `${BE_GESTIONMESSAGERIE_SEARCH_RECIPIENTS_URL}/?establishment_id=${establishmentId}&q=${encodeURIComponent(query)}`;
|
||||
return fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
.then(requestResponseHandler)
|
||||
.catch(errorHandler);
|
||||
/**
|
||||
* Recherche des destinataires pour la messagerie
|
||||
*/
|
||||
export const searchMessagerieRecipients = async (
|
||||
establishmentId,
|
||||
query,
|
||||
csrfToken
|
||||
) => {
|
||||
try {
|
||||
const baseUrl = BE_GESTIONMESSAGERIE_SEARCH_RECIPIENTS_URL.endsWith('/')
|
||||
? BE_GESTIONMESSAGERIE_SEARCH_RECIPIENTS_URL
|
||||
: BE_GESTIONMESSAGERIE_SEARCH_RECIPIENTS_URL + '/';
|
||||
|
||||
const url = `${baseUrl}?establishment_id=${establishmentId}&q=${encodeURIComponent(query)}`;
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: buildHeaders(csrfToken),
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
return await requestResponseHandler(response);
|
||||
} catch (error) {
|
||||
logger.error('Erreur lors de la recherche des destinataires:', error);
|
||||
return errorHandler(error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Marque des messages comme lus
|
||||
*/
|
||||
export const markAsRead = async (conversationId, userId, csrfToken) => {
|
||||
try {
|
||||
const response = await fetch(BE_GESTIONMESSAGERIE_MARK_AS_READ_URL, {
|
||||
method: 'POST',
|
||||
headers: buildHeaders(csrfToken),
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({
|
||||
conversation_id: conversationId,
|
||||
user_id: userId,
|
||||
}),
|
||||
});
|
||||
return await requestResponseHandler(response);
|
||||
} catch (error) {
|
||||
logger.error('Erreur lors du marquage des messages comme lus:', error);
|
||||
return errorHandler(error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Upload un fichier pour la messagerie
|
||||
*/
|
||||
export const uploadFile = async (
|
||||
file,
|
||||
conversationId,
|
||||
senderId,
|
||||
csrfToken,
|
||||
onProgress = null
|
||||
) => {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('conversation_id', conversationId);
|
||||
formData.append('sender_id', senderId);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
if (onProgress) {
|
||||
xhr.upload.addEventListener('progress', (event) => {
|
||||
if (event.lengthComputable) {
|
||||
const percentComplete = (event.loaded / event.total) * 100;
|
||||
onProgress(percentComplete);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
xhr.addEventListener('load', () => {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
try {
|
||||
const response = JSON.parse(xhr.responseText);
|
||||
resolve(response);
|
||||
} catch (error) {
|
||||
reject(new Error('Réponse invalide du serveur'));
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const errorResponse = JSON.parse(xhr.responseText);
|
||||
reject(new Error(errorResponse.message || "Erreur lors de l'upload"));
|
||||
} catch {
|
||||
reject(new Error(`Erreur HTTP: ${xhr.status}`));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
xhr.addEventListener('error', () => {
|
||||
reject(new Error("Erreur réseau lors de l'upload"));
|
||||
});
|
||||
|
||||
xhr.addEventListener('timeout', () => {
|
||||
reject(new Error("Timeout lors de l'upload"));
|
||||
});
|
||||
|
||||
xhr.open('POST', BE_GESTIONMESSAGERIE_UPLOAD_FILE_URL);
|
||||
xhr.withCredentials = true;
|
||||
xhr.timeout = 30000;
|
||||
|
||||
// Ajouter le header CSRF pour XMLHttpRequest
|
||||
if (csrfToken) {
|
||||
xhr.setRequestHeader('X-CSRFToken', csrfToken);
|
||||
}
|
||||
|
||||
xhr.send(formData);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Supprime une conversation
|
||||
*/
|
||||
export const deleteConversation = async (conversationId, csrfToken) => {
|
||||
try {
|
||||
const url = `${BE_GESTIONMESSAGERIE_DELETE_CONVERSATION_URL}/${conversationId}/`;
|
||||
const response = await fetch(url, {
|
||||
method: 'DELETE',
|
||||
headers: buildHeaders(csrfToken),
|
||||
credentials: 'include',
|
||||
});
|
||||
return await requestResponseHandler(response);
|
||||
} catch (error) {
|
||||
logger.error('Erreur lors de la suppression de la conversation:', error);
|
||||
return errorHandler(error);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user