UNPKG

analytica-frontend-lib

Version:

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

1,299 lines (1,245 loc) 70 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _chunkHGWU3GUNjs = require('./chunk-HGWU3GUN.js'); var _chunkNEDUOGWUjs = require('./chunk-NEDUOGWU.js'); var _chunkCMUIZOUVjs = require('./chunk-CMUIZOUV.js'); var _chunkRIVDFVR5js = require('./chunk-RIVDFVR5.js'); var _chunkBJMKBBN3js = require('./chunk-BJMKBBN3.js'); var _chunkTCLRDUMFjs = require('./chunk-TCLRDUMF.js'); var _chunk34ST3MKOjs = require('./chunk-34ST3MKO.js'); var _chunkANT66KVKjs = require('./chunk-ANT66KVK.js'); var _chunkTN3AYOMVjs = require('./chunk-TN3AYOMV.js'); // src/components/SimulatedPerformance/useSimulatedPerformance.tsx var _react = require('react'); var _reactrouterdom = require('react-router-dom'); // src/components/GeneralOverviewSection/GeneralOverviewSection.tsx var _jsxruntime = require('react/jsx-runtime'); function AreaCard({ area, scoreType = "percentage" /* PERCENTAGE */ }) { const bgColor = _chunkTN3AYOMVjs.hexToRgba.call(void 0, area.color, 0.1); return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0 flex flex-col items-center justify-center p-4 rounded-xl", style: { backgroundColor: bgColor }, children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-8 h-8 flex items-center justify-center rounded-full mb-2", style: { backgroundColor: area.color }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkRIVDFVR5js.IconRender_default, { iconName: area.icon, size: 18, color: "white" }) } ), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", weight: "semibold", className: "text-center uppercase text-text-700 mb-1 line-clamp-2", children: area.name } ), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "lg", weight: "bold", className: "text-text-950", children: _chunkTN3AYOMVjs.formatScore.call(void 0, area.percentage, scoreType) }) ] } ); } function EssayCard({ essay }) { const bgColor = _chunkTN3AYOMVjs.hexToRgba.call(void 0, essay.color, 0.1); return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0 flex flex-col items-center justify-center p-4 rounded-xl", style: { backgroundColor: bgColor }, children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-8 h-8 flex items-center justify-center rounded-full mb-2", style: { backgroundColor: essay.color }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkRIVDFVR5js.IconRender_default, { iconName: essay.icon, size: 18, color: "white" }) } ), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", weight: "semibold", className: "text-center uppercase text-text-700 mb-1 line-clamp-2", children: essay.name } ), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "lg", weight: "bold", className: "text-text-950", children: _chunkTN3AYOMVjs.formatScore.call(void 0, essay.percentage, "percentage" /* PERCENTAGE */) }) ] } ); } function AreaCardSkeleton() { return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0 flex flex-col items-center justify-center p-4 rounded-xl bg-background-50", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNEDUOGWUjs.SkeletonRounded, { className: "h-8 w-8 rounded-full mb-2" }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNEDUOGWUjs.SkeletonRounded, { className: "h-3 w-16 mb-1" }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNEDUOGWUjs.SkeletonRounded, { className: "h-6 w-12" }) ] }); } function GeneralOverviewSection({ data, loading = false, error = null, scoreType = "percentage" /* PERCENTAGE */ }) { if (error) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "p-4 bg-error-50 border border-error-200 rounded-xl", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-error-700", children: error }) }); } if (loading) { return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-4 p-5 bg-background border border-border-50 rounded-xl", children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-1", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "lg", weight: "bold", className: "text-text-950", children: "Geral" }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNEDUOGWUjs.SkeletonRounded, { className: "h-4 w-3/4" }) ] }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-4", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNEDUOGWUjs.SkeletonRounded, { className: "h-3 w-full rounded-full" }) }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNEDUOGWUjs.SkeletonRounded, { className: "h-6 w-12" }) ] }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex gap-3", children: [1, 2, 3, 4, 5].map((i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AreaCardSkeleton, {}, i)) }) ] }); } if (!data) { return null; } return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-4 p-5 bg-background border border-border-50 rounded-xl", children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-1", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "lg", weight: "bold", className: "text-text-950", children: "Geral" }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-text-500", children: "Dados que mostram a profici\xEAncia de todos os simulados digitais j\xE1 realizados em todas as \xE1reas do conhecimento" }) ] }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-4", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCMUIZOUVjs.ProgressBar_default, { value: scoreType === "tri" /* TRI */ ? data.overallPercentage / 10 : data.overallPercentage, variant: "green", size: "small" } ) }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "lg", weight: "bold", className: "text-text-950 min-w-[50px] text-right", children: _chunkTN3AYOMVjs.formatScore.call(void 0, data.overallPercentage, scoreType) } ) ] }), (data.areas.length > 0 || data.essay) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-3", children: [ data.areas.map((area) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AreaCard, { area, scoreType }, area.id)), data.essay && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EssayCard, { essay: data.essay }) ] }) ] }); } // src/components/GeneralOverviewSection/useGeneralOverview.ts var initialState = { data: null, loading: false, isRefreshing: false, error: null }; function useGeneralOverview(api) { const [state, setState] = _react.useState.call(void 0, initialState); const requestIdRef = _react.useRef.call(void 0, 0); const fetchOverview = _react.useCallback.call(void 0, async (params, refresh = false) => { const currentRequestId = ++requestIdRef.current; setState((prev) => ({ ...prev, loading: !refresh, isRefreshing: refresh, error: null })); try { let url = "/performance/simulated/general-overview"; if (params.scoreType && params.scoreType !== "percentage") { url += `?scoreType=${params.scoreType}`; } const body = { period: params.period, schoolIds: params.schoolIds || [], schoolYearIds: params.schoolYearIds || [], classIds: params.classIds || [] }; const response = await api.post(url, body); if (currentRequestId !== requestIdRef.current) return; setState({ data: response.data.data, loading: false, isRefreshing: false, error: null }); } catch (err) { if (currentRequestId !== requestIdRef.current) return; const errorMessage = err instanceof Error ? err.message : "Erro ao carregar dados gerais de desempenho"; console.error("Error fetching general overview:", err); setState((prev) => ({ ...prev, loading: false, isRefreshing: false, error: errorMessage })); } }, [api] ); const reset = _react.useCallback.call(void 0, () => { requestIdRef.current++; setState(initialState); }, []); return { ...state, fetchOverview, reset }; } // src/components/SimulatedStudentsOverview/useSimulatedOverview.ts // src/components/SimulatedStudentDetailsModal/types.ts var SIMULATED_PERFORMANCE_TAG_CONFIG = { ["HIGHLIGHT" /* HIGHLIGHT */]: { label: "Destaque da turma", variant: "success" /* SUCCESS */ }, ["ABOVE_AVERAGE" /* ABOVE_AVERAGE */]: { label: "Acima da m\xE9dia", variant: "info" /* INFO */ }, ["BELOW_AVERAGE" /* BELOW_AVERAGE */]: { label: "Abaixo da m\xE9dia", variant: "warning" /* WARNING */ }, ["ATTENTION_POINT" /* ATTENTION_POINT */]: { label: "Ponto de aten\xE7\xE3o", variant: "error" /* ERROR */ } }; var PerformanceBadgeAction = /* @__PURE__ */ ((PerformanceBadgeAction2) => { PerformanceBadgeAction2["SUCCESS"] = "success"; PerformanceBadgeAction2["INFO"] = "info"; PerformanceBadgeAction2["WARNING"] = "warning"; PerformanceBadgeAction2["ERROR"] = "error"; return PerformanceBadgeAction2; })(PerformanceBadgeAction || {}); var PERFORMANCE_TAG_TO_BADGE_ACTION = { ["HIGHLIGHT" /* HIGHLIGHT */]: "success" /* SUCCESS */, ["ABOVE_AVERAGE" /* ABOVE_AVERAGE */]: "info" /* INFO */, ["BELOW_AVERAGE" /* BELOW_AVERAGE */]: "warning" /* WARNING */, ["ATTENTION_POINT" /* ATTENTION_POINT */]: "error" /* ERROR */ }; var ReportSimulationType = /* @__PURE__ */ ((ReportSimulationType2) => { ReportSimulationType2["ENEM_1"] = "enem-1"; ReportSimulationType2["ENEM_2"] = "enem-2"; ReportSimulationType2["ESSAYS"] = "essays"; return ReportSimulationType2; })(ReportSimulationType || {}); function isStudentSubjectsData(data) { return "subjects" in data; } function isStudentContentsData(data) { return "contents" in data; } function simulationTypeToActivityFilters(simulationType) { switch (simulationType) { case "enem-1" /* ENEM_1 */: return { types: ["SIMULADO"], subtypes: ["ENEM_PROVA_1"] }; case "enem-2" /* ENEM_2 */: return { types: ["SIMULADO"], subtypes: ["ENEM_PROVA_2"] }; default: return {}; } } // src/components/SimulatedStudentsOverview/utils.ts function getErrorMessage(err, fallbackMessage) { return err instanceof Error ? err.message : fallbackMessage; } function isStudentsData(data, type) { return type === "students" && data !== null && !("totalClasses" in data) && !("totalMunicipalities" in data); } function isClassesData(data, type) { return type === "classes" && data !== null && "totalClasses" in data; } function isMunicipalitiesData(data, type) { return type === "municipalities" && data !== null && "totalMunicipalities" in data; } // src/components/SimulatedStudentsOverview/useSimulatedOverview.ts function buildEndpoint(simulationType, scoreType) { if (simulationType === "essays") { const params2 = new URLSearchParams(); if (scoreType && scoreType !== "percentage") { params2.append("scoreType", scoreType); } const queryString2 = params2.toString(); const endpoint2 = "/performance/simulated/essays/students-overview"; if (!queryString2) { return endpoint2; } return `${endpoint2}?${queryString2}`; } const activityFilters = simulationTypeToActivityFilters(simulationType); const params = new URLSearchParams(); _optionalChain([activityFilters, 'access', _ => _.types, 'optionalAccess', _2 => _2.forEach, 'call', _3 => _3((t) => params.append("types", t))]); _optionalChain([activityFilters, 'access', _4 => _4.statuses, 'optionalAccess', _5 => _5.forEach, 'call', _6 => _6((s) => params.append("statuses", s))]); if (scoreType && scoreType !== "percentage") { params.append("scoreType", scoreType); } const queryString = params.toString(); const endpoint = "/performance/simulated/activities/students-overview"; if (!queryString) { return endpoint; } return `${endpoint}?${queryString}`; } var initialState2 = { data: null, loading: false, isRefreshing: false, error: null }; function useSimulatedOverview(api) { const [data, setData] = _react.useState.call(void 0, initialState2.data ); const [loading, setLoading] = _react.useState.call(void 0, initialState2.loading); const [isRefreshing, setIsRefreshing] = _react.useState.call(void 0, initialState2.isRefreshing); const [error, setError] = _react.useState.call(void 0, initialState2.error); const requestIdRef = _react.useRef.call(void 0, 0); const paramsToBody2 = (params) => { return { period: params.period, subjectId: params.subjectId, areaKnowledgeId: params.areaKnowledgeId, schoolIds: params.schoolIds, schoolYearIds: params.schoolYearIds, classIds: params.classIds, studentsIds: params.studentsIds, page: _nullishCoalesce(params.page, () => ( 1)), limit: _nullishCoalesce(params.limit, () => ( 10)), orderBy: _nullishCoalesce(params.orderBy, () => ( "name")), order: _nullishCoalesce(params.order, () => ( "asc")) }; }; const fetchOverview = _react.useCallback.call(void 0, async (params, refresh = false) => { const currentRequestId = ++requestIdRef.current; try { if (refresh) { setIsRefreshing(true); } else { setLoading(true); } setError(null); const endpoint = buildEndpoint(params.simulationType, params.scoreType); const body = paramsToBody2(params); const response = await api.post( endpoint, body ); if (currentRequestId !== requestIdRef.current) return; setData(response.data.data); } catch (err) { if (currentRequestId !== requestIdRef.current) return; setError( getErrorMessage( err, "N\xE3o foi poss\xEDvel carregar os dados de simulados" ) ); } finally { if (currentRequestId === requestIdRef.current) { setLoading(false); setIsRefreshing(false); } } }, [api] ); const reset = _react.useCallback.call(void 0, () => { requestIdRef.current++; setData(initialState2.data); setLoading(initialState2.loading); setIsRefreshing(initialState2.isRefreshing); setError(initialState2.error); }, []); return { data, loading, isRefreshing, error, fetchOverview, reset }; } // src/components/SimulatedStudentsOverview/useAggregatedOverview.ts function buildEndpoint2(aggregationType, simulationType, scoreType) { if (simulationType === "essays") { return "/performance/simulated/essays/students-overview"; } const activityFilters = simulationTypeToActivityFilters(simulationType); const params = new URLSearchParams(); params.append("aggregationType", aggregationType); _optionalChain([activityFilters, 'access', _7 => _7.types, 'optionalAccess', _8 => _8.forEach, 'call', _9 => _9((t) => params.append("types", t))]); _optionalChain([activityFilters, 'access', _10 => _10.statuses, 'optionalAccess', _11 => _11.forEach, 'call', _12 => _12((s) => params.append("statuses", s))]); if (scoreType && scoreType !== "percentage") { params.append("scoreType", scoreType); } const basePath = "/performance/simulated/activities/overview"; return `${basePath}?${params.toString()}`; } var initialState3 = { data: null, loading: false, isRefreshing: false, error: null }; function useAggregatedOverview(api) { const [data, setData] = _react.useState.call(void 0, initialState3.data ); const [loading, setLoading] = _react.useState.call(void 0, initialState3.loading); const [isRefreshing, setIsRefreshing] = _react.useState.call(void 0, initialState3.isRefreshing); const [error, setError] = _react.useState.call(void 0, initialState3.error); const requestIdRef = _react.useRef.call(void 0, 0); const paramsToBody2 = (params) => { return { period: params.period, subjectId: params.subjectId, areaKnowledgeId: params.areaKnowledgeId, schoolIds: params.schoolIds, schoolYearIds: params.schoolYearIds, classIds: params.classIds, studentsIds: params.studentsIds }; }; const fetchOverview = _react.useCallback.call(void 0, async (params, refresh = false) => { const currentRequestId = ++requestIdRef.current; try { if (refresh) { setIsRefreshing(true); } else { setLoading(true); } setError(null); const endpoint = buildEndpoint2( params.aggregationType, params.simulationType, params.scoreType ); const body = paramsToBody2(params); let responseData; switch (params.aggregationType) { case "classes": { const response = await api.post( endpoint, body ); responseData = response.data.data; break; } case "municipalities": { const response = await api.post( endpoint, body ); responseData = response.data.data; break; } case "students": default: { const response = await api.post( endpoint, body ); responseData = response.data.data; break; } } if (currentRequestId !== requestIdRef.current) return; setData(responseData); } catch (err) { if (currentRequestId !== requestIdRef.current) return; setError( getErrorMessage(err, "N\xE3o foi poss\xEDvel carregar os dados de overview") ); } finally { if (currentRequestId === requestIdRef.current) { setLoading(false); setIsRefreshing(false); } } }, [api] ); const reset = _react.useCallback.call(void 0, () => { requestIdRef.current++; setData(initialState3.data); setLoading(initialState3.loading); setIsRefreshing(initialState3.isRefreshing); setError(initialState3.error); }, []); return { data, loading, isRefreshing, error, fetchOverview, reset }; } // src/components/SimulatedContentsPerformance/useSimulatedContents.ts function buildEndpoint3(simulationType, scoreType) { if (simulationType === "essays" /* ESSAYS */) { return null; } const activityFilters = simulationTypeToActivityFilters(simulationType); const params = new URLSearchParams(); _optionalChain([activityFilters, 'access', _13 => _13.types, 'optionalAccess', _14 => _14.forEach, 'call', _15 => _15((t) => params.append("types", t))]); _optionalChain([activityFilters, 'access', _16 => _16.statuses, 'optionalAccess', _17 => _17.forEach, 'call', _18 => _18((s) => params.append("statuses", s))]); if (scoreType && scoreType !== "percentage") { params.append("scoreType", scoreType); } const queryString = params.toString(); const endpoint = "/performance/simulated/activities/contents-performance"; if (!queryString) { return endpoint; } return `${endpoint}?${queryString}`; } function useSimulatedContents(api) { const [data, setData] = _react.useState.call(void 0, null); const [loading, setLoading] = _react.useState.call(void 0, false); const [isRefreshing, setIsRefreshing] = _react.useState.call(void 0, false); const [error, setError] = _react.useState.call(void 0, null); const isFirstLoad = _react.useRef.call(void 0, true); const latestRequestId = _react.useRef.call(void 0, 0); const isCurrentRequest = (requestId) => requestId === latestRequestId.current; const buildRequestBody = (params) => ({ period: params.period, subjectId: params.subjectId && params.subjectId !== "all" ? params.subjectId : void 0, areaKnowledgeId: params.areaKnowledgeId && params.areaKnowledgeId !== "all" ? params.areaKnowledgeId : void 0, schoolIds: params.schoolIds, schoolYearIds: params.schoolYearIds, classIds: params.classIds, studentsIds: params.studentsIds, page: _nullishCoalesce(params.page, () => ( 1)), limit: _nullishCoalesce(params.limit, () => ( 10)), orderBy: _nullishCoalesce(params.orderBy, () => ( "correctPercentage")), order: _nullishCoalesce(params.order, () => ( "asc")) }); const handleNoEndpoint = (requestId) => { if (!isCurrentRequest(requestId)) { return; } setData(null); setError(null); setLoading(false); setIsRefreshing(false); isFirstLoad.current = true; }; const startRequestState = (requestId, refresh) => { if (!isCurrentRequest(requestId)) { return; } if (isFirstLoad.current && !refresh) { setLoading(true); } else { setIsRefreshing(true); } setError(null); }; const handleSuccess = (requestId, response) => { if (!isCurrentRequest(requestId)) { return; } setData(response.data.data); isFirstLoad.current = false; }; const handleError = (requestId, err) => { if (!isCurrentRequest(requestId)) { return; } const errorMessage = err instanceof Error ? err.message : "Erro ao carregar dados de habilidades"; setError(errorMessage); setData(null); }; const finishRequestState = (requestId) => { if (!isCurrentRequest(requestId)) { return; } setLoading(false); setIsRefreshing(false); }; const fetchContents = _react.useCallback.call(void 0, async (params, refresh = false) => { const localRequestId = ++latestRequestId.current; const endpoint = buildEndpoint3(params.simulationType, params.scoreType); if (!endpoint) { handleNoEndpoint(localRequestId); return; } startRequestState(localRequestId, refresh); try { const response = await api.post( endpoint, buildRequestBody(params) ); handleSuccess(localRequestId, response); } catch (err) { handleError(localRequestId, err); } finally { finishRequestState(localRequestId); } }, [api] ); const reset = _react.useCallback.call(void 0, () => { setData(null); setLoading(false); setIsRefreshing(false); setError(null); isFirstLoad.current = true; }, []); return { data, loading, isRefreshing, error, fetchContents, reset }; } // src/components/AreaKnowledgeSelector/AreaKnowledgeSelector.tsx var _GridFour = require('@phosphor-icons/react/dist/csr/GridFour'); // src/components/AreaKnowledgeSelector/types.ts var ESSAY_AREA_ID = "essay"; // src/components/AreaKnowledgeSelector/AreaKnowledgeSelector.tsx function AreaKnowledgeSelector({ areas, selectedAreaId, onAreaChange, loading = false, label = "\xC1rea de conhecimento", includeEssay = true }) { const selectItems = _react.useMemo.call(void 0, () => { const allOption = { id: "all", name: "Todos" }; const areaItems = areas.map( (area) => ({ id: area.id, name: area.name, color: area.color }) ); const items = [allOption, ...areaItems]; if (includeEssay) { const essayOption = { id: ESSAY_AREA_ID, name: "Reda\xE7\xE3o" }; items.push(essayOption); } return items; }, [areas, includeEssay]); const handleValueChange = (value) => { if (value === "all") { onAreaChange(null); } else { onAreaChange(value); } }; const effectiveValue = selectedAreaId || "all"; return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-2", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", weight: "medium", className: "text-text-700", children: label }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "relative", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkHGWU3GUNjs.Select_default, { defaultValue: "all", value: effectiveValue, onValueChange: handleValueChange, children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkHGWU3GUNjs.SelectTrigger, { className: _chunkTN3AYOMVjs.cn.call(void 0, "w-full", loading && "opacity-50"), disabled: loading, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkHGWU3GUNjs.SelectValue, { placeholder: "Selecione uma \xE1rea" }) } ), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkHGWU3GUNjs.SelectContent, { children: selectItems.map((item) => { let itemIcon = null; if (item.id === "all") { itemIcon = /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "w-[21px] h-[21px] flex items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _GridFour.GridFourIcon, { size: 17, weight: "bold", className: "text-gray-600" } ) }); } else if (item.color) { itemIcon = /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "w-[21px] h-[21px] flex items-center justify-center rounded-sm", style: { backgroundColor: `${item.color}20` }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "w-2 h-2 rounded-full", style: { backgroundColor: item.color } } ) } ); } return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkHGWU3GUNjs.SelectItem, { value: item.id, disabled: loading, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2", children: [ itemIcon, /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "whitespace-nowrap", children: item.name }) ] }) }, item.id); }) }) ] } ) }) ] }); } // src/components/SimulatedStudentDetailsModal/SimulatedStudentDetailsModal.tsx var _ArrowLeft = require('@phosphor-icons/react/dist/csr/ArrowLeft'); var _CaretRight = require('@phosphor-icons/react/dist/csr/CaretRight'); // src/components/SimulatedStudentDetailsModal/useSimulatedStudentDetails.ts // src/components/SimulatedStudentDetailsModal/utils.ts function paramsToBody(params) { return { userInstitutionId: params.userInstitutionId, period: params.period, subjectId: _nullishCoalesce(params.subjectId, () => ( void 0)), page: _nullishCoalesce(params.page, () => ( 1)), limit: _nullishCoalesce(params.limit, () => ( 20)) }; } // src/components/SimulatedStudentDetailsModal/useSimulatedStudentDetails.ts function buildEndpoint4(simulationType) { if (simulationType === "essays" /* ESSAYS */) { return "/performance/simulated/essays/student-details"; } const activityFilters = simulationTypeToActivityFilters(simulationType); const params = new URLSearchParams(); _optionalChain([activityFilters, 'access', _19 => _19.types, 'optionalAccess', _20 => _20.forEach, 'call', _21 => _21((t) => params.append("types", t))]); _optionalChain([activityFilters, 'access', _22 => _22.statuses, 'optionalAccess', _23 => _23.forEach, 'call', _24 => _24((s) => params.append("statuses", s))]); const queryString = params.toString(); const endpoint = "/performance/simulated/activities/student-details"; if (!queryString) { return endpoint; } return `${endpoint}?${queryString}`; } function useSimulatedStudentDetails(api) { const [data, setData] = _react.useState.call(void 0, null); const [loading, setLoading] = _react.useState.call(void 0, false); const [error, setError] = _react.useState.call(void 0, null); const requestIdRef = _react.useRef.call(void 0, 0); const fetchDetails = _react.useCallback.call(void 0, async (params) => { const currentRequestId = ++requestIdRef.current; try { setLoading(true); setError(null); setData(null); const endpoint = buildEndpoint4(params.simulationType); const body = paramsToBody(params); const response = await api.post( endpoint, body ); if (currentRequestId !== requestIdRef.current) return; setData(response.data.data); } catch (err) { if (currentRequestId !== requestIdRef.current) return; const errorMessage = err instanceof Error ? err.message : "N\xE3o foi poss\xEDvel carregar os detalhes do estudante"; setData(null); setError(errorMessage); } finally { if (currentRequestId === requestIdRef.current) { setLoading(false); } } }, [api] ); const reset = _react.useCallback.call(void 0, () => { requestIdRef.current++; setData(null); setLoading(false); setError(null); }, []); return { data, loading, error, fetchDetails, reset }; } // src/components/SimulatedStudentDetailsModal/SimulatedStudentDetailsModal.tsx function SimulatedStudentDetailsModal({ api, isOpen, onClose, simulationType, userInstitutionId, studentName, period }) { const { data, loading, error, fetchDetails, reset } = useSimulatedStudentDetails(api); const [selectedSubject, setSelectedSubject] = _react.useState.call(void 0, null); _react.useEffect.call(void 0, () => { if (isOpen && userInstitutionId) { fetchDetails({ simulationType, userInstitutionId, period, subjectId: null }); } }, [isOpen, userInstitutionId, simulationType, period, fetchDetails]); _react.useEffect.call(void 0, () => { if (!isOpen) { reset(); setSelectedSubject(null); } }, [isOpen, reset]); const handleSubjectClick = _react.useCallback.call(void 0, (subject) => { if (!userInstitutionId) return; setSelectedSubject({ id: subject.id, name: subject.name }); fetchDetails({ simulationType, userInstitutionId, period, subjectId: subject.id }); }, [userInstitutionId, simulationType, period, fetchDetails] ); const handleBack = _react.useCallback.call(void 0, () => { if (!userInstitutionId) return; setSelectedSubject(null); fetchDetails({ simulationType, userInstitutionId, period, subjectId: null }); }, [userInstitutionId, simulationType, period, fetchDetails]); const modalTitle = selectedSubject ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk34ST3MKOjs.Button_default, { onClick: handleBack, variant: "raw", className: "p-1 hover:bg-background-100 rounded-md transition-colors", "aria-label": "Voltar para lista de mat\xE9rias", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _ArrowLeft.ArrowLeftIcon, { size: 20, className: "text-text-600" }) } ), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { children: selectedSubject.name }) ] }) : `Desempenho de ${studentName || "Estudante"}`; if (loading) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkTCLRDUMFjs.Modal_default, { isOpen, onClose, title: modalTitle, size: "lg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-text-500", children: "Carregando..." }) }) }); } if (error) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkTCLRDUMFjs.Modal_default, { isOpen, onClose, title: modalTitle, size: "lg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-error-500", children: error }) }) }); } if (!data) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkTCLRDUMFjs.Modal_default, { isOpen, onClose, title: modalTitle, size: "lg", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-text-500", children: "Nenhum dado encontrado" }) }) }); } const isSubjectsLevel = isStudentSubjectsData(data); const renderDetailsContent = () => { if (isSubjectsLevel) { if (data.subjects.length > 0) { return data.subjects.map((subject) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SubjectItem, { subject, onClick: () => handleSubjectClick(subject), questionsLabel: "quest\xF5es" }, subject.id )); } return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-text-500 text-center py-4", children: "Nenhuma mat\xE9ria encontrada" }); } if (data.contents.length > 0) { return data.contents.map((content) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContentItem, { content, questionsLabel: "quest\xF5es", ofLabel: "de" }, content.contentId )); } return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-text-500 text-center py-4", children: "Nenhuma habilidade encontrada" }); }; const detailsContent = renderDetailsContent(); return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkTCLRDUMFjs.Modal_default, { isOpen, onClose, title: modalTitle, size: "lg", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-4", children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-between p-4 bg-background-50 rounded-xl", children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-1", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "md", weight: "semibold", className: "text-text-950", children: data.student.name }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-text-500", children: [ data.student.school, " - ", data.student.class ] }) ] }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-end gap-1", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "lg", weight: "bold", className: "text-text-950", children: _chunkTN3AYOMVjs.formatPercentageRounded.call(void 0, data.student.average) }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkBJMKBBN3js.Badge_default, { variant: "solid", action: PERFORMANCE_TAG_TO_BADGE_ACTION[data.student.performance], size: "small", children: SIMULATED_PERFORMANCE_TAG_CONFIG[data.student.performance].label } ) ] }) ] }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex flex-col gap-2 max-h-[400px] overflow-y-auto", children: detailsContent }) ] }) }); } function SubjectItem({ subject, onClick, questionsLabel }) { return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { onClick, className: "flex items-center gap-4 p-4 bg-background border border-border-50 rounded-xl hover:bg-background-50 transition-colors text-left w-full", children: [ subject.color && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-3 h-3 rounded-full flex-shrink-0", style: { backgroundColor: subject.color } } ), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", weight: "semibold", className: "text-text-950 truncate", children: subject.name }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", className: "text-text-500", children: [ subject.questionsCount, " ", questionsLabel ] }) ] }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-32 flex-shrink-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCMUIZOUVjs.ProgressBar_default, { value: subject.performance.correctPercentage, variant: "green", size: "small", showPercentage: true } ) }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _CaretRight.CaretRightIcon, { size: 16, className: "text-text-400 flex-shrink-0" }) ] } ); } function ContentItem({ content, questionsLabel, ofLabel }) { return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-4 p-4 bg-background border border-border-50 rounded-xl", children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", weight: "semibold", className: "text-text-950 truncate", children: content.contentName }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2", children: [ content.bnccCode && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", className: "text-primary-600", children: content.bnccCode }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", className: "text-text-500", children: [ content.questionsCount, " ", questionsLabel ] }) ] }) ] }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-32 flex-shrink-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkCMUIZOUVjs.ProgressBar_default, { value: content.performance.correctPercentage, variant: "green", size: "small", showPercentage: true } ) }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1 flex-shrink-0", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", weight: "semibold", className: "text-success-600", children: content.performance.correct }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", className: "text-text-500 whitespace-nowrap", children: [ ofLabel, " ", content.questionsCount ] }) ] }) ] }); } // src/utils/profileAggregation.ts function getAggregationTypeByProfile(profileName) { switch (profileName) { case "UNIT_MANAGER" /* UNIT_MANAGER */: return "classes"; case "REGIONAL_MANAGER" /* REGIONAL_MANAGER */: return "municipalities"; case "GENERAL_MANAGER" /* GENERAL_MANAGER */: case "TEACHER" /* TEACHER */: default: return "students"; } } function shouldUseAggregatedOverview(profileName) { return profileName === "UNIT_MANAGER" /* UNIT_MANAGER */ || profileName === "REGIONAL_MANAGER" /* REGIONAL_MANAGER */; } // src/components/SimulatedPerformance/types.ts var SimulatedViewTab = /* @__PURE__ */ ((SimulatedViewTab2) => { SimulatedViewTab2["STUDENTS"] = "students"; SimulatedViewTab2["SKILLS"] = "skills"; return SimulatedViewTab2; })(SimulatedViewTab || {}); // src/components/SimulatedPerformance/useSimulatedPerformance.tsx function SimulatedPerformanceTagCell({ row }) { const tagConfig = SIMULATED_PERFORMANCE_TAG_CONFIG[row.performance]; return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkBJMKBBN3js.Badge_default, { variant: "solid", action: tagConfig.variant, size: "small", children: tagConfig.label }); } function ContentPerformanceCell({ percentage }) { const getColorClass = () => { if (percentage >= 70) { return "bg-success-500"; } if (percentage >= 50) { return "bg-warning-500"; } return "bg-error-500"; }; const colorClass = getColorClass(); return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-center gap-2", children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "text-sm text-text-950 min-w-[40px]", children: [ Math.round(percentage), "%" ] }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-16 h-2 bg-background-100 rounded-full overflow-hidden", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `h-full rounded-full ${colorClass}`, style: { width: `${percentage}%` } } ) }) ] }); } var centeredColumn = { sortable: true, className: "py-3 px-4 text-center", align: "center" }; var centeredContentsColumn = { sortable: true, className: "py-3 px-4 text-center", align: "center" }; var simulatedTableColumnsBase = [ { key: "name", label: "Nome", sortable: true, className: "py-3 px-4 text-start" }, { key: "school", label: "Escola", sortable: false, className: "py-3 px-4 text-start" }, { ...centeredColumn, key: "schoolYear", label: "Ano", width: "80px", sortable: false }, { ...centeredColumn, key: "class", label: "Turma", width: "80px", sortable: false }, { ...centeredColumn, key: "average", label: "M\xE9dia", width: "100px" }, { ...centeredColumn, key: "performance", label: "Desempenho", width: "160px" } ]; var contentsTableColumns = [ { key: "contentName", label: "Habilidade", sortable: true, className: "py-3 px-4 text-start" }, { key: "subject", label: "Componente", sortable: false, className: "py-3 px-4 text-start", render: (_value, row) => row.subject.name }, { ...centeredContentsColumn, key: "simulatedExamsCount", label: "Simulados", width: "100px" }, { ...centeredContentsColumn, key: "questionsCount", label: "Quest\xF5es", width: "100px" }, { ...centeredContentsColumn, key: "studentsCount", label: "Estudantes", width: "100px" }, { ...centeredContentsColumn, key: "performance", label: "Desempenho", width: "160px", render: (_value, row) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContentPerformanceCell, { percentage: row.performance.correctPercentage }) } ]; function useSimulatedPerformance({ api, profileName, enabled = true }) { const [searchParams, setSearchParams] = _reactrouterdom.useSearchParams.call(void 0, ); const aggregationType = _react.useMemo.call(void 0, () => getAggregationTypeByProfile(profileName), [profileName] ); const period = _react.useMemo.call(void 0, () => { const periodParam = searchParams.get("period"); if (periodParam === "7_DAYS") return "7_DAYS"; if (periodParam === "1_MONTH") return "1_MONTH"; if (periodParam === "3_MONTHS") return "3_MONTHS"; if (periodParam === "6_MONTHS") return "6_MONTHS"; if (periodParam === "1_YEAR") return "1_YEAR"; return "1_MONTH"; }, [searchParams]); const scoreType = _react.useMemo.call(void 0, () => { const scoreTypeParam = searchParams.get("scoreType"); if (scoreTypeParam === "tri") return "tri" /* TRI */; return "percentage" /* PERCENTAGE */; }, [searchParams]); const [selectedAreaKnowledgeId, setSelectedAreaKnowledgeId] = _react.useState.call(void 0, null); const [selectedAreaRelatedIds, setSelectedAreaRelatedIds] = _react.useState.call(void 0, []); const [selectedSubjectId, setSelectedSubjectId] = _react.useState.call(void 0, null ); const [simulatedViewTab, setSimulatedViewTab] = _react.useState.call(void 0, "students" /* STUDENTS */ ); const [isStudentModalOpen, setIsStudentModalOpen] = _react.useState.call(void 0, false); const [selectedStudent, setSelectedStudent] = _react.useState.call(void 0, null); const [isContentModalOpen, setIsContentModalOpen] = _react.useState.call(void 0, false); const [selectedContent, setSelectedContent] = _react.useState.call(void 0, null); const [isFiltersModalOpen, setIsFiltersModalOpen] = _react.useState.call(void 0, false); const [filters, setFilters] = _react.useState.call(void 0, { schoolIds: [], schoolYearIds: [], classIds: [], studentsIds: [] }); const selectedAreaKnowledgeIdRef = _react.useRef.call(void 0, selectedAreaKnowledgeId ); const selectedSubjectIdRef = _react.useRef.call(void 0, selectedSubjectId); const filtersRef = _react.useRef.call(void 0, filters); const simulatedViewTabRef = _react.useRef.call(void 0, simulatedViewTab); const scoreTypeRef = _react.useRef.call(void 0, scoreType); const periodRef = _react.useRef.call(void 0, period); const aggregationTypeRef = _react.useRef.call(void 0, aggregationType); _react.useEffect.call(void 0, () => { selectedAreaKnowledgeIdRef.current = selectedAreaKnowledgeId; }, [selectedAreaKnowledgeId]); _react.useEffect.call(void 0, () => { selectedSubjectIdRef.current = selectedSubjectId; }, [selectedSubjectId]); _react.useEffect.call(void 0, () => { filtersRef.current = filters; }, [filters]); _react.useEffect.call(void 0, () => { simulatedViewTabRef.current = simulatedViewTab; }, [simulatedViewTab]); _react.useEffect.call(void 0, () => { scoreTypeRef.current = scoreType; }, [scoreType]); _react.useEffect.call(void 0, () => { periodRef.current = period; }, [period]); _react.useEffect.call(void 0, () => { aggregationTypeRef.current = aggregationType; }, [aggregationType]); const { data: generalOverviewData, loading: generalOverviewLoading, error: generalOverviewError, fetchOverview: fetchGeneralOverview } = useGeneralOverview(api); const { data: aggregatedData, loading: aggregatedLoading, isRefreshing: aggregatedRefreshing, error: aggregatedError, fetchOverview: fetchAggregatedOverview } = useAggregatedOverview(api); const { data: simulatedData, loading: simulatedLoading, isRefreshing: simulatedRefreshing, error: simulatedError, fetchOverview: fetchSimulatedOverview } = useSimulatedOverview(api); const { data: contentsData, loading: contentsLoading, isRefreshing: contentsRefreshing, error: contentsError, fetchContents } = useSimulatedContents(api); const isEssaySelected = selectedAreaKnowledgeId === ESSAY_AREA_ID; const activeFiltersCount = _react.useMemo.call(void 0, () => { let count = 0; if (filters.schoolIds.length > 0) count++; if (filters.schoolYearIds.length > 0) count++; if (filters.classIds.length > 0) count++; if (filters.studentsIds.length > 0) count++; return count; }, [filters]); _react.useEffect.call(void 0, () => { if (!selectedAreaKnowledgeId || !_optionalChain([generalOverviewData, 'optionalAccess', _25 => _25.areas])) { return; } const area = generalOverviewData.areas.find( (a) => a.id === selectedAreaKnowledgeId ); const relatedIds = _nullishCoalesce(_optionalChain([area, 'optiona