feat: initialisation complète du projet CESIZen
- Backend Laravel 11 (API REST, JWT auth, PostgreSQL) - Frontend Next.js 14 (React, TypeScript, Tailwind CSS) - Docker Compose (PostgreSQL, backend, frontend) - Modules : auth, profil, tracker émotions, informations, admin
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
BarChart,
|
||||
Bar,
|
||||
XAxis,
|
||||
YAxis,
|
||||
CartesianGrid,
|
||||
Tooltip,
|
||||
ResponsiveContainer,
|
||||
PieChart,
|
||||
Pie,
|
||||
Cell,
|
||||
LineChart,
|
||||
Line,
|
||||
Legend,
|
||||
} from 'recharts';
|
||||
import type { RapportData } from '@/types';
|
||||
|
||||
interface EmotionChartProps {
|
||||
data: RapportData;
|
||||
type?: 'repartition' | 'evolution' | 'intensite';
|
||||
}
|
||||
|
||||
export default function EmotionChart({ data, type = 'repartition' }: EmotionChartProps) {
|
||||
if (type === 'repartition') {
|
||||
const pieData = data.repartition.map((item) => ({
|
||||
name: item.nom,
|
||||
value: item.count,
|
||||
color: item.couleur,
|
||||
pourcentage: item.pourcentage,
|
||||
}));
|
||||
|
||||
if (pieData.length === 0) {
|
||||
return <EmptyChart message="Aucune donnée pour cette période" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full h-80">
|
||||
<ResponsiveContainer width="100%" height={320}>
|
||||
<PieChart>
|
||||
<Pie
|
||||
data={pieData}
|
||||
cx="50%"
|
||||
cy="50%"
|
||||
innerRadius={60}
|
||||
outerRadius={120}
|
||||
paddingAngle={3}
|
||||
dataKey="value"
|
||||
label={({ name, pourcentage }: any) => `${name} (${pourcentage}%)`}
|
||||
>
|
||||
{pieData.map((entry, index) => (
|
||||
<Cell key={`cell-${index}`} fill={entry.color} />
|
||||
))}
|
||||
</Pie>
|
||||
<Tooltip
|
||||
formatter={(value: any, name: any) => [`${value} saisies`, name]}
|
||||
contentStyle={{
|
||||
backgroundColor: 'rgba(255,255,255,0.95)',
|
||||
border: 'none',
|
||||
borderRadius: '12px',
|
||||
boxShadow: '0 4px 12px rgba(0,0,0,0.1)',
|
||||
}}
|
||||
/>
|
||||
</PieChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (type === 'evolution') {
|
||||
const lineData = data.evolution.labels.map((label, index) => {
|
||||
const point: Record<string, string | number> = { date: label };
|
||||
data.evolution.emotions.forEach((emotion) => {
|
||||
point[emotion.nom] = emotion.data[index] || 0;
|
||||
});
|
||||
return point;
|
||||
});
|
||||
|
||||
if (lineData.length === 0) {
|
||||
return <EmptyChart message="Aucune donnée d'évolution" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full h-80">
|
||||
<ResponsiveContainer width="100%" height={320}>
|
||||
<LineChart data={lineData}>
|
||||
<CartesianGrid strokeDasharray="3 3" className="opacity-30" />
|
||||
<XAxis dataKey="date" tick={{ fontSize: 12 }} />
|
||||
<YAxis tick={{ fontSize: 12 }} />
|
||||
<Tooltip
|
||||
contentStyle={{
|
||||
backgroundColor: 'rgba(255,255,255,0.95)',
|
||||
border: 'none',
|
||||
borderRadius: '12px',
|
||||
boxShadow: '0 4px 12px rgba(0,0,0,0.1)',
|
||||
}}
|
||||
/>
|
||||
<Legend />
|
||||
{data.evolution.emotions.map((emotion) => (
|
||||
<Line
|
||||
key={emotion.nom}
|
||||
type="monotone"
|
||||
dataKey={emotion.nom}
|
||||
stroke={emotion.couleur}
|
||||
strokeWidth={2}
|
||||
dot={{ fill: emotion.couleur, r: 4 }}
|
||||
activeDot={{ r: 6 }}
|
||||
/>
|
||||
))}
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (type === 'intensite') {
|
||||
const barData = data.evolution.labels.map((label, index) => ({
|
||||
date: label,
|
||||
intensite: data.evolution.intensite_moyenne[index] || 0,
|
||||
}));
|
||||
|
||||
if (barData.length === 0) {
|
||||
return <EmptyChart message="Aucune donnée d'intensité" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full h-80">
|
||||
<ResponsiveContainer width="100%" height={320}>
|
||||
<BarChart data={barData}>
|
||||
<CartesianGrid strokeDasharray="3 3" className="opacity-30" />
|
||||
<XAxis dataKey="date" tick={{ fontSize: 12 }} />
|
||||
<YAxis domain={[0, 10]} tick={{ fontSize: 12 }} />
|
||||
<Tooltip
|
||||
contentStyle={{
|
||||
backgroundColor: 'rgba(255,255,255,0.95)',
|
||||
border: 'none',
|
||||
borderRadius: '12px',
|
||||
boxShadow: '0 4px 12px rgba(0,0,0,0.1)',
|
||||
}}
|
||||
formatter={(value: any) => [`${Number(value).toFixed(1)}`, 'Intensité moyenne']}
|
||||
/>
|
||||
<Bar dataKey="intensite" fill="#fce117" radius={[6, 6, 0, 0]} />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function EmptyChart({ message }: { message: string }) {
|
||||
return (
|
||||
<div className="w-full h-80 flex items-center justify-center text-gray-400 dark:text-gray-600">
|
||||
<p className="text-lg">{message}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user