Initial commit
This commit is contained in:
165
components/stats-pie-chart.tsx
Normal file
165
components/stats-pie-chart.tsx
Normal file
@@ -0,0 +1,165 @@
|
||||
"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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user