Tu veux adapter la syntaxe de ton endpoint GetMessages en utilisant une approche similaire à
ton Update avec MediatR et DTOs ? Voici comment tu peux le faire :
✨ Nouvelle version avec MediatR et DTOs
[HttpGet]
public async Task<ActionResult<PaginatedChatMessagesResponseDto>>
GetMessages(
[FromQuery] int pageNumber = 1,
[FromQuery] int pageSize = 10)
{
if (pageNumber <= 0 || pageSize <= 0)
{
return BadRequest("Le numéro de page et la taille de page doivent
être supérieurs à 0.");
}
var query = new GetPaginatedChatMessagesQuery
{
PageNumber = pageNumber,
PageSize = pageSize
};
var result = await _mediator.Send(query);
if (result == null || ![Link]())
{
return NotFound("Aucun message trouvé.");
}
return Ok(result);
}
🎯 Explication
Utilisation de MediatR : On envoie une requête
(GetPaginatedChatMessagesQuery) au handler via _mediator.Send(query).
Utilisation d’un DTO : On retourne PaginatedChatMessagesResponseDto pour
structurer la réponse.
📌 1️⃣ DTOs : Structure de réponse
public class PaginatedChatMessagesResponseDto
{
public int PageNumber { get; set; }
public int PageSize { get; set; }
public int TotalMessages { get; set; }
public int TotalPages { get; set; }
public List<ChatMessageInfoResponseDto> Messages { get; set; } = new();
}
public class ChatMessageInfoResponseDto
{
public int MessageId { get; set; }
public int AccountId { get; set; }
public bool Sent { get; set; }
public bool Received { get; set; }
public bool Lire { get; set; }
public bool Replied { get; set; }
public DateTime LastUpdateDate { get; set; }
}
📌 2️⃣ Query (Requête MediatR)
public class GetPaginatedChatMessagesQuery :
IRequest<PaginatedChatMessagesResponseDto>
{
public int PageNumber { get; set; }
public int PageSize { get; set; }
}
📌 3️⃣ Handler pour récupérer les messages
public class GetPaginatedChatMessagesHandler :
IRequestHandler<GetPaginatedChatMessagesQuery,
PaginatedChatMessagesResponseDto>
{
private readonly IChatMessageRepository _chatMessageRepository;
public GetPaginatedChatMessagesHandler(IChatMessageRepository
chatMessageRepository)
{
_chatMessageRepository = chatMessageRepository;
}
public async Task<PaginatedChatMessagesResponseDto>
Handle(GetPaginatedChatMessagesQuery request, CancellationToken
cancellationToken)
{
var messages = await
_chatMessageRepository.GetMessagesAsync([Link],
[Link]);
var totalMessages = await
_chatMessageRepository.GetTotalMessagesCountAsync();
var totalPages = (int)[Link]((double)totalMessages /
[Link]);
return new PaginatedChatMessagesResponseDto
{
PageNumber = [Link],
PageSize = [Link],
TotalMessages = totalMessages,
TotalPages = totalPages,
Messages = [Link](m => new ChatMessageInfoResponseDto
{
MessageId = [Link],
AccountId = [Link],
Sent = [Link],
Received = [Link],
Lire = [Link],
Replied = [Link],
LastUpdateDate = [Link]
}).ToList()
};
}
}
✅ Avantages de cette approche
1. MediatR : Permet de séparer la logique métier du contrôleur.
2. DTOs : Assure une réponse bien structurée et facile à gérer côté frontend.
3. Scalabilité : Facile à modifier et maintenir.
Tu veux une version avec Filtrage ou Tri ? 😃
Voici comment organiser votre code en séparant la logique de récupération des données dans
un fichier service, puis en l’utilisant dans votre composant.
1. Créer un fichier service ([Link])
Créez un fichier [Link] dans votre dossier services (ou un autre dossier de
votre choix) et mettez-y la logique de récupération des données :
📁 services/[Link]
import axios from "axios";
const API_BASE_URL = "[Link]
export const fetchTotalAmounts = async () => {
try {
const [noteRes, etfRes, sharedRes, boundRes] = await [Link]([
[Link](`${API_BASE_URL}/Note/total-amount`),
[Link](`${API_BASE_URL}/etf/total-amount`),
[Link](`${API_BASE_URL}/shares/total-amount`),
[Link](`${API_BASE_URL}/bonds/total-amount`),
]);
return {
noteCount: [Link],
etfCount: [Link],
sharedCount: [Link],
boundCount: [Link],
};
} catch (error) {
[Link]("Error fetching data:", error);
return {
noteCount: 0,
etfCount: 0,
sharedCount: 0,
boundCount: 0,
};
}
};
2. Importer et utiliser le service dans votre composant
Maintenant, utilisez ce service dans votre composant [Link] :
📁 components/[Link]
import { useState, useEffect } from "react";
import { fetchTotalAmounts } from "../services/securityService"; // Import
du service
const TitleGraphe = () => {
// State management
const [etfCount, setEtfCount] = useState(0);
const [boundCount, setBoundCount] = useState(0);
const [noteCount, setNoteCount] = useState(0);
const [sharedCount, setSharedCount] = useState(0);
useEffect(() => {
const fetchData = async () => {
const data = await fetchTotalAmounts();
setNoteCount([Link]);
setEtfCount([Link]);
setSharedCount([Link]);
setBoundCount([Link]);
};
fetchData();
}, []);
return (
<div>
<h2>ETF Count: {etfCount}</h2>
<h2>Bound Count: {boundCount}</h2>
<h2>Note Count: {noteCount}</h2>
<h2>Shared Count: {sharedCount}</h2>
</div>
);
};
export default TitleGraphe;
✅ Avantages de cette approche
1. Séparation des préoccupations : La logique de récupération des données est dans
[Link], ce qui rend [Link] plus lisible.
2. Réutilisabilité : Le service peut être utilisé par d'autres composants si nécessaire.
3. Facilité de maintenance : Si l’API change, vous n’aurez qu’à modifier [Link]
sans toucher aux composants.
Tu peux maintenant appeler fetchTotalAmounts() n'importe où pour récupérer les données
sans répéter la logique. 🚀
//Deuxieme code
D'accord ! Tu veux séparer la logique des requêtes API dans un fichier de service et garder le composant React propre. Voici comment tu
peux organiser ton code :
1. Créer un service pour les requêtes API
Dans le dossier services, crée un fichier [Link] :
📂 src/services/[Link]
import axios from "axios";
const API_BASE_URL = "[Link]
export const fetchNoteCount = () => [Link](`${API_BASE_URL}/Note/total-amount`);
export const fetchEtfCount = () => [Link](`${API_BASE_URL}/etf/total-amount`);
export const fetchSharedCount = () => [Link](`${API_BASE_URL}/shares/total-amount`);
export const fetchBoundCount = () => [Link](`${API_BASE_URL}/bonds/total-amount`);
2. Mettre à jour le composant TitleGraphe
Modifie ton composant pour utiliser ce service :
📂 src/components/[Link]
import React, { useEffect, useState } from "react";
import { fetchNoteCount, fetchEtfCount, fetchSharedCount, fetchBoundCount } from "../services/securityService";
const TitleGraphe = () => {
const [etfCount, setEtfFinalCount] = useState(0);
const [boundCount, setBoundCount] = useState(0);
const [noteCount, setNoteCount] = useState(0);
const [sharedCount, setSharedCount] = useState(0);
useEffect(() => {
fetchNoteCount()
.then(response => setNoteCount([Link]))
.catch(error => [Link](error));
fetchEtfCount()
.then(response => setEtfFinalCount([Link]))
.catch(error => [Link](error));
fetchSharedCount()
.then(response => setSharedCount([Link]))
.catch(error => [Link](error));
fetchBoundCount()
.then(response => setBoundCount([Link]))
.catch(error => [Link](error));
}, []);
return (
<>
<div className="widget-heading d-flex justify-content-between align-items-center">
<h3 className="m-0 card-title">Types Securities</h3>
</div>
<div className="row">
<div className="swiper swiper-container course-slider">
<div className="swiper-wrapper">
<div className="swiper-slide">
<div className="card counter">
<div className="card-body d-flex align-items-center p-4">
<div className="card-box-icon me-3 me-xl-4">
<h4>ETF: {etfCount}</h4>
<h4>Bonds: {boundCount}</h4>
<h4>Notes: {noteCount}</h4>
<h4>Shares: {sharedCount}</h4>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</>
);
};
export default TitleGraphe;
Avantages de cette approche
✅ Code organisé : Séparation de la logique métier (service) et de l'affichage (composant).
✅ Réutilisable : Le service peut être utilisé ailleurs sans dupliquer du code.
✅ Facile à maintenir : Les modifications d'API se font uniquement dans le fichier [Link].
C'est une bonne pratique pour structurer ton projet React 🚀.