analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
312 lines (310 loc) • 11.1 kB
JavaScript
import {
DEFAULT_PERFORMANCE_DETAILS_LABELS
} from "./chunk-ILQ33JG4.mjs";
import {
MetricBox
} from "./chunk-G5AMZYLQ.mjs";
import {
CardAccordation
} from "./chunk-2ACDTDO4.mjs";
import {
ProgressBar_default
} from "./chunk-LDBWF6EA.mjs";
import {
Badge_default
} from "./chunk-OEW3ST4F.mjs";
import {
Modal_default
} from "./chunk-TNLGS7SB.mjs";
import {
Text_default
} from "./chunk-IMCIR6TJ.mjs";
// src/components/StudentPerformanceDetailsModal/StudentPerformanceDetailsModal.tsx
import { useMemo } from "react";
import { UserIcon, TrophyIcon, XCircleIcon } from "@phosphor-icons/react";
import { jsx, jsxs } from "react/jsx-runtime";
var STAT_CARD_COLORS = {
orange: {
headerBg: "bg-warning-background",
iconBg: "bg-warning-300",
valueColor: "text-warning-600",
secondaryLabelColor: "text-warning-500"
},
green: {
headerBg: "bg-success-200",
iconBg: "bg-success-300",
valueColor: "text-success-700",
secondaryLabelColor: "text-success-600"
},
red: {
headerBg: "bg-error-100",
iconBg: "bg-error-500",
valueColor: "text-error-700",
secondaryLabelColor: "text-error-300"
},
default: {
headerBg: "bg-warning-background",
iconBg: "bg-warning-300",
valueColor: "text-warning-600",
secondaryLabelColor: "text-warning-500"
}
};
var PerformanceStatCard = ({
icon,
label,
value,
secondaryLabel,
badgeText,
variant
}) => {
const colors = STAT_CARD_COLORS[variant] ?? STAT_CARD_COLORS.default;
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col rounded-xl border border-border-50 bg-background overflow-hidden flex-1", children: [
/* @__PURE__ */ jsxs(
"div",
{
className: `flex flex-col items-center justify-center px-2 sm:px-3 py-2 gap-1 ${colors.headerBg}`,
children: [
/* @__PURE__ */ jsx(
Text_default,
{
as: "span",
className: `size-8 rounded-full flex items-center justify-center ${colors.iconBg}`,
children: icon
}
),
/* @__PURE__ */ jsx(
Text_default,
{
size: "2xs",
weight: "medium",
className: "text-text-800 uppercase text-center leading-none",
children: label
}
),
/* @__PURE__ */ jsx(
Text_default,
{
size: "xl",
weight: "bold",
className: `${colors.valueColor} text-center`,
children: value
}
)
]
}
),
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 px-2 sm:px-3 py-2", children: [
/* @__PURE__ */ jsx(
Text_default,
{
size: "2xs",
weight: "medium",
className: `${colors.secondaryLabelColor} uppercase text-center`,
children: secondaryLabel
}
),
/* @__PURE__ */ jsx(Badge_default, { size: "large", action: "info", children: badgeText || "-" })
] })
] });
};
var formatProgressText = (template, correct, total) => {
return template.replace("{correct}", String(correct)).replace("{total}", String(total));
};
var ActivityAccordionCard = ({
activity,
noDataMessage,
activityProgressText,
activityDetailsUnavailable
}) => {
const hasData = !activity.hasNoData && activity.totalCount > 0;
const progressPercentage = hasData ? Math.min(
100,
Math.max(0, activity.correctCount / activity.totalCount * 100)
) : 0;
return /* @__PURE__ */ jsx(
CardAccordation,
{
value: activity.id,
className: "bg-background rounded-xl border border-border-50",
triggerClassName: "p-4",
contentClassName: "px-4 pb-4",
trigger: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 flex-1", children: [
/* @__PURE__ */ jsx(Text_default, { size: "lg", weight: "bold", className: "text-text-950", children: activity.name }),
hasData ? /* @__PURE__ */ jsxs("div", { className: "flex flex-row items-center gap-2", children: [
/* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
ProgressBar_default,
{
value: progressPercentage,
variant: "green",
size: "medium"
}
) }),
/* @__PURE__ */ jsx(
Text_default,
{
size: "xs",
weight: "medium",
className: "text-text-950 whitespace-nowrap",
children: formatProgressText(
activityProgressText,
activity.correctCount,
activity.totalCount
)
}
)
] }) : /* @__PURE__ */ jsx(Text_default, { size: "xs", className: "text-text-500", children: noDataMessage })
] }),
children: /* @__PURE__ */ jsx(Text_default, { size: "sm", className: "text-text-700", children: activity.description || activityDetailsUnavailable })
}
);
};
var LoadingSkeleton = () => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 animate-pulse", children: [
/* @__PURE__ */ jsx("div", { className: "h-6 bg-background-200 rounded w-48" }),
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-3 gap-2", children: [
/* @__PURE__ */ jsx("div", { className: "h-48 bg-background-200 rounded-xl" }),
/* @__PURE__ */ jsx("div", { className: "h-48 bg-background-200 rounded-xl" }),
/* @__PURE__ */ jsx("div", { className: "h-48 bg-background-200 rounded-xl" })
] }),
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-2", children: [
/* @__PURE__ */ jsx("div", { className: "h-20 bg-background-200 rounded-xl" }),
/* @__PURE__ */ jsx("div", { className: "h-20 bg-background-200 rounded-xl" })
] }),
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-3 gap-2", children: [
/* @__PURE__ */ jsx("div", { className: "h-20 bg-background-200 rounded-xl" }),
/* @__PURE__ */ jsx("div", { className: "h-20 bg-background-200 rounded-xl" }),
/* @__PURE__ */ jsx("div", { className: "h-20 bg-background-200 rounded-xl" })
] })
] });
var ErrorContent = ({ message }) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-8 gap-3", children: [
/* @__PURE__ */ jsx(
Text_default,
{
as: "span",
className: "size-12 rounded-full bg-error-100 flex items-center justify-center",
children: /* @__PURE__ */ jsx(XCircleIcon, { size: 24, className: "text-error-700", weight: "fill" })
}
),
/* @__PURE__ */ jsx(Text_default, { size: "md", className: "text-error-700 text-center", children: message })
] });
var PerformanceContent = ({
data,
labels
}) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pt-2", children: [
/* @__PURE__ */ jsx(
Text_default,
{
as: "span",
className: "size-6 rounded-full bg-primary-100 flex items-center justify-center",
children: /* @__PURE__ */ jsx(UserIcon, { size: 14, className: "text-primary-800", weight: "fill" })
}
),
/* @__PURE__ */ jsx(Text_default, { size: "md", className: "text-text-950", children: data.studentName })
] }),
/* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row gap-2 sm:gap-3", children: [
/* @__PURE__ */ jsx(
PerformanceStatCard,
{
icon: /* @__PURE__ */ jsx(TrophyIcon, { size: 16, weight: "fill", className: "text-white" }),
label: labels.gradeLabel,
value: data.grade.value.toFixed(1),
secondaryLabel: labels.performanceTagLabel,
badgeText: data.grade.performanceLabel,
variant: "orange"
}
),
/* @__PURE__ */ jsx(
PerformanceStatCard,
{
icon: /* @__PURE__ */ jsx(TrophyIcon, { size: 16, weight: "fill", className: "text-text-950" }),
label: labels.correctQuestionsLabel,
value: data.correctQuestions.value,
secondaryLabel: labels.bestResultLabel,
badgeText: data.correctQuestions.bestResultTopic,
variant: "green"
}
),
/* @__PURE__ */ jsx(
PerformanceStatCard,
{
icon: /* @__PURE__ */ jsx(XCircleIcon, { size: 16, weight: "fill", className: "text-white" }),
label: labels.incorrectQuestionsLabel,
value: data.incorrectQuestions.value,
secondaryLabel: labels.hardestTopicLabel,
badgeText: data.incorrectQuestions.hardestTopic,
variant: "red"
}
)
] }),
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-2 sm:gap-3", children: [
/* @__PURE__ */ jsx(
MetricBox,
{
label: labels.activitiesLabel,
value: data.activitiesCompleted
}
),
/* @__PURE__ */ jsx(MetricBox, { label: labels.questionsLabel, value: data.questionsAnswered })
] }),
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-3 gap-2 sm:gap-3", children: [
/* @__PURE__ */ jsx(MetricBox, { label: labels.accessCountLabel, value: data.accessCount }),
/* @__PURE__ */ jsx(MetricBox, { label: labels.timeOnlineLabel, value: data.timeOnline }),
/* @__PURE__ */ jsx(MetricBox, { label: labels.lastLoginLabel, value: data.lastLogin })
] }),
data.activities.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 pt-4", children: [
/* @__PURE__ */ jsx(Text_default, { size: "lg", weight: "bold", className: "text-text-950", children: labels.activitiesProgressTitle }),
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: data.activities.map((activity) => /* @__PURE__ */ jsx(
ActivityAccordionCard,
{
activity,
noDataMessage: labels.noDataMessage,
activityProgressText: labels.activityProgressText,
activityDetailsUnavailable: labels.activityDetailsUnavailable
},
activity.id
)) })
] })
] });
var renderModalContent = (loading, error, data, labels) => {
if (loading) {
return /* @__PURE__ */ jsx(LoadingSkeleton, {});
}
if (error) {
return /* @__PURE__ */ jsx(ErrorContent, { message: error });
}
if (data) {
return /* @__PURE__ */ jsx(PerformanceContent, { data, labels });
}
return null;
};
var StudentPerformanceDetailsModal = ({
isOpen,
onClose,
data,
loading = false,
error = null,
labels: customLabels
}) => {
const labels = useMemo(
() => ({ ...DEFAULT_PERFORMANCE_DETAILS_LABELS, ...customLabels }),
[customLabels]
);
if (!data && !loading && !error) {
return null;
}
return /* @__PURE__ */ jsx(
Modal_default,
{
isOpen,
onClose,
title: labels.title,
size: "lg",
contentClassName: "max-h-[80vh] overflow-y-auto",
children: renderModalContent(loading, error, data, labels)
}
);
};
export {
StudentPerformanceDetailsModal
};
//# sourceMappingURL=chunk-WPIILK4I.mjs.map