166 lines
5.0 KiB
TypeScript
166 lines
5.0 KiB
TypeScript
"use client"
|
||
|
||
import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip, Legend } from "recharts"
|
||
|
||
interface Stats {
|
||
no_report: number
|
||
in_shelter: number
|
||
not_in_shelter: number
|
||
no_alarm: number
|
||
safe_after_exit: number
|
||
}
|
||
|
||
interface StatsPieChartProps {
|
||
stats: Stats
|
||
onCategoryClick: (category: string, categoryName: string) => void
|
||
}
|
||
|
||
const COLORS = {
|
||
no_report: "#ef4444", // red-500
|
||
in_shelter: "#22c55e", // green-500
|
||
not_in_shelter: "#f97316", // orange-500
|
||
no_alarm: "#3b82f6", // blue-500
|
||
safe_after_exit: "#10b981",
|
||
}
|
||
|
||
export function StatsPieChart({ stats, onCategoryClick }: StatsPieChartProps) {
|
||
console.log("StatsPieChart received stats:", stats)
|
||
|
||
// Create data array - always include all categories for testing
|
||
const data = [
|
||
{
|
||
name: "לא דיווחו",
|
||
value: Number(stats?.no_report) || 0,
|
||
category: "no_report",
|
||
color: COLORS.no_report,
|
||
},
|
||
{
|
||
name: "במקלט/חדר מוגן",
|
||
value: Number(stats?.in_shelter) || 0,
|
||
category: "in_shelter",
|
||
color: COLORS.in_shelter,
|
||
},
|
||
{
|
||
name: "לא במקלט",
|
||
value: Number(stats?.not_in_shelter) || 0,
|
||
category: "not_in_shelter",
|
||
color: COLORS.not_in_shelter,
|
||
},
|
||
{
|
||
name: "אין אזעקה",
|
||
value: Number(stats?.no_alarm) || 0,
|
||
category: "no_alarm",
|
||
color: COLORS.no_alarm,
|
||
},
|
||
{
|
||
name: "אני בטוח.ה (סוף אירוע)",
|
||
value: Number(stats?.safe_after_exit) || 0,
|
||
category: "safe_after_exit",
|
||
color: COLORS.safe_after_exit,
|
||
}
|
||
]
|
||
|
||
console.log("Pie chart data:", data)
|
||
|
||
// Calculate total for testing
|
||
const total = data.reduce((sum, item) => sum + item.value, 0)
|
||
console.log("Total value:", total)
|
||
|
||
// If no real data, create sample data for testing
|
||
const displayData =
|
||
total === 0
|
||
? [
|
||
{ name: "לא דיווחו", value: 1, category: "no_report", color: COLORS.no_report },
|
||
{ name: "במקלט/חדר מוגן", value: 2, category: "in_shelter", color: COLORS.in_shelter },
|
||
{ name: "לא במקלט", value: 1, category: "not_in_shelter", color: COLORS.not_in_shelter },
|
||
{ name: "אין אזעקה", value: 3, category: "no_alarm", color: COLORS.no_alarm },
|
||
{ name: "אני בטוח.ה (סוף אירוע)", value: 1, category: "safe_after_exit", color: COLORS.safe_after_exit },
|
||
]
|
||
: data.filter((item) => item.value > 0)
|
||
|
||
const CustomTooltip = ({ active, payload }: any) => {
|
||
if (active && payload && payload.length) {
|
||
const data = payload[0].payload
|
||
return (
|
||
<div className="bg-white p-3 border rounded-lg shadow-lg" dir="rtl">
|
||
<p className="font-semibold text-gray-800">{data.name}</p>
|
||
<p className="text-sm text-gray-600">כמות: {data.value}</p>
|
||
<p className="text-xs text-gray-500">לחץ לפירוט</p>
|
||
</div>
|
||
)
|
||
}
|
||
return null
|
||
}
|
||
|
||
const handleClick = (data: any) => {
|
||
console.log("Pie chart clicked:", data)
|
||
if (data && data.category) {
|
||
onCategoryClick(data.category, data.name)
|
||
}
|
||
}
|
||
|
||
const renderCustomLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, value, name }: any) => {
|
||
const RADIAN = Math.PI / 180
|
||
const radius = innerRadius + (outerRadius - innerRadius) * 0.5
|
||
const x = cx + radius * Math.cos(-midAngle * RADIAN)
|
||
const y = cy + radius * Math.sin(-midAngle * RADIAN)
|
||
|
||
return (
|
||
<text
|
||
x={x}
|
||
y={y}
|
||
fill="white"
|
||
textAnchor={x > cx ? "start" : "end"}
|
||
dominantBaseline="central"
|
||
fontSize={12}
|
||
fontWeight="bold"
|
||
style={{ textShadow: "1px 1px 2px rgba(0,0,0,0.7)" }}
|
||
>
|
||
{value}
|
||
</text>
|
||
)
|
||
}
|
||
|
||
return (
|
||
<div className="h-80 w-full">
|
||
<div className="text-xs text-gray-500 mb-2 text-center">
|
||
{total === 0 ? "נתוני דוגמה (אין משתמשים)" : `סה"כ: ${total} משתמשים`}
|
||
</div>
|
||
|
||
<ResponsiveContainer width="100%" height="90%">
|
||
<PieChart>
|
||
<Pie
|
||
data={displayData}
|
||
cx="50%"
|
||
cy="50%"
|
||
labelLine={false}
|
||
label={renderCustomLabel}
|
||
outerRadius={100}
|
||
innerRadius={0}
|
||
fill="#8884d8"
|
||
dataKey="value"
|
||
onClick={handleClick}
|
||
className="cursor-pointer"
|
||
stroke="#fff"
|
||
strokeWidth={2}
|
||
>
|
||
{displayData.map((entry, index) => (
|
||
<Cell key={`cell-${index}`} fill={entry.color} className="hover:opacity-80 transition-opacity" />
|
||
))}
|
||
</Pie>
|
||
<Tooltip content={<CustomTooltip />} />
|
||
<Legend
|
||
wrapperStyle={{
|
||
direction: "rtl",
|
||
textAlign: "center",
|
||
paddingTop: "10px",
|
||
}}
|
||
formatter={(value, entry: any) => <span style={{ color: entry.color, fontWeight: "bold" }}>{value}</span>}
|
||
/>
|
||
</PieChart>
|
||
</ResponsiveContainer>
|
||
|
||
</div>
|
||
)
|
||
}
|