UNPKG

analytica-frontend-lib

Version:

Repositório público dos componentes utilizados nas plataformas da Analytica Ensino

224 lines (216 loc) 8.8 kB
"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