analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
224 lines (216 loc) • 8.8 kB
JavaScript
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
var _chunkANT66KVKjs = require('./chunk-ANT66KVK.js');
var _chunkTN3AYOMVjs = require('./chunk-TN3AYOMV.js');
// src/components/ProficiencyChart/ProficiencyChart.tsx
var _react = require('react');
var _jsxruntime = require('react/jsx-runtime');
var buildSlices = (counters, total) => {
if (total === 0) return [];
return [
{
key: "attentionPoint",
label: "Ponto de aten\xE7\xE3o",
value: counters.attentionPoint,
percentage: counters.attentionPoint / total * 100,
colorClass: "bg-error-600",
fillColor: "#dc2626"
// error-600
},
{
key: "belowAverage",
label: "Abaixo da m\xE9dia",
value: counters.belowAverage,
percentage: counters.belowAverage / total * 100,
colorClass: "bg-warning-400",
fillColor: "#fbbf24"
// warning-400
},
{
key: "aboveAverage",
label: "Acima da m\xE9dia",
value: counters.aboveAverage,
percentage: counters.aboveAverage / total * 100,
colorClass: "bg-success-400",
fillColor: "#4ade80"
// success-400
},
{
key: "highlight",
label: "Destaque da turma",
value: counters.highlight,
percentage: counters.highlight / total * 100,
colorClass: "bg-success-700",
fillColor: "#15803d"
// success-700
}
];
};
var CHART_SIZE = 180;
var PieChart = ({
slices,
hoveredSlice,
onSliceHover
}) => {
const total = slices.reduce((sum, s) => sum + s.value, 0);
if (total === 0) {
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-center w-[180px] h-[180px] bg-background-50 rounded-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-text-500", children: "Sem dados" }) });
}
const cx = CHART_SIZE / 2;
const cy = CHART_SIZE / 2;
const radius = CHART_SIZE / 2 - 5;
let cumulativePercent = 0;
const paths = slices.map((slice) => {
const percent = slice.percentage;
const startPercent = cumulativePercent;
cumulativePercent += percent;
if (percent === 0) return null;
const startAngle = startPercent / 100 * 360 - 90;
const endAngle = (startPercent + percent) / 100 * 360 - 90;
const startRad = startAngle * Math.PI / 180;
const endRad = endAngle * Math.PI / 180;
const x1 = cx + radius * Math.cos(startRad);
const y1 = cy + radius * Math.sin(startRad);
const x2 = cx + radius * Math.cos(endRad);
const y2 = cy + radius * Math.sin(endRad);
const largeArc = percent > 50 ? 1 : 0;
const d = percent >= 100 ? `M ${cx - radius} ${cy} A ${radius} ${radius} 0 1 1 ${cx + radius} ${cy} A ${radius} ${radius} 0 1 1 ${cx - radius} ${cy}` : `M ${cx} ${cy} L ${x1} ${y1} A ${radius} ${radius} 0 ${largeArc} 1 ${x2} ${y2} Z`;
const midAngle = (startPercent + percent / 2) / 100 * 360 - 90;
const midRad = midAngle * Math.PI / 180;
const labelRadius = radius * 0.65;
const labelX = cx + labelRadius * Math.cos(midRad);
const labelY = cy + labelRadius * Math.sin(midRad);
const isOtherHovered = hoveredSlice && hoveredSlice !== slice.key;
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "g", { children: [
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
"path",
{
d,
className: "cursor-pointer transition-opacity",
style: { fill: slice.fillColor, opacity: isOtherHovered ? 0.3 : 1 },
onMouseEnter: () => onSliceHover(slice.key),
onMouseLeave: () => onSliceHover(null)
}
),
percent >= 8 && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
"text",
{
x: labelX,
y: labelY,
textAnchor: "middle",
dominantBaseline: "middle",
className: "fill-white text-xs font-semibold pointer-events-none",
style: {
textShadow: "0 1px 2px rgba(0,0,0,0.3)",
opacity: isOtherHovered ? 0.3 : 1
},
children: [
slice.percentage.toFixed(0),
"%"
]
}
)
] }, slice.key);
});
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
"svg",
{
viewBox: `0 0 ${CHART_SIZE} ${CHART_SIZE}`,
className: "w-[180px] h-[180px]",
children: paths
}
);
};
var ProficiencyChart = ({
counters,
totalStudents,
className,
...props
}) => {
const [hoveredSlice, setHoveredSlice] = _react.useState.call(void 0, null);
const total = _nullishCoalesce(totalStudents, () => ( 0));
const slices = _react.useMemo.call(void 0, () => {
if (!counters) return [];
return buildSlices(counters, total);
}, [counters, total]);
if (!counters || total === 0) {
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
"div",
{
className: _chunkTN3AYOMVjs.cn.call(void 0,
"flex items-center justify-center h-[200px] bg-background border border-border-50 rounded-xl",
className
),
...props,
children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-text-500", children: "Sem dados de profici\xEAncia dispon\xEDveis" })
}
);
}
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
"div",
{
className: _chunkTN3AYOMVjs.cn.call(void 0,
"w-full bg-background border border-border-50 rounded-xl p-5",
className
),
...props,
children: [
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { as: "h3", size: "md", weight: "semibold", className: "text-text-950 mb-4", children: "Profici\xEAncia por quantidade de estudante" }),
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-between gap-6", children: [
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-3", children: [
slices.map((slice) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
"div",
{
className: _chunkTN3AYOMVjs.cn.call(void 0,
"flex items-center gap-3 cursor-pointer transition-opacity",
hoveredSlice && hoveredSlice !== slice.key && "opacity-50"
),
onMouseEnter: () => setHoveredSlice(slice.key),
onMouseLeave: () => setHoveredSlice(null),
children: [
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
"span",
{
className: _chunkTN3AYOMVjs.cn.call(void 0,
"w-3 h-3 rounded-full shrink-0",
slice.colorClass
)
}
),
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col", children: [
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", weight: "medium", className: "text-text-950", children: slice.label }),
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", className: "text-text-500", children: [
slice.value.toLocaleString("pt-BR"),
" ",
slice.value === 1 ? "aluno" : "alunos",
" (",
slice.percentage.toFixed(1),
"%)"
] })
] })
]
},
slice.key
)),
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pt-2 border-t border-border-100", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", weight: "semibold", className: "text-text-950", children: [
"Total: ",
total.toLocaleString("pt-BR"),
" ",
total === 1 ? "aluno" : "alunos"
] }) })
] }),
/* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "shrink-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
PieChart,
{
slices,
hoveredSlice,
onSliceHover: setHoveredSlice
}
) })
] })
]
}
);
};
var ProficiencyChart_default = ProficiencyChart;
exports.ProficiencyChart = ProficiencyChart; exports.ProficiencyChart_default = ProficiencyChart_default;
//# sourceMappingURL=chunk-C44WQ6PT.js.map