analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
359 lines (357 loc) • 12.4 kB
JavaScript
import {
DEFAULT_LESSON_PROGRESS_LABELS
} from "./chunk-MZMT6JJX.mjs";
import {
CardActivitiesResults
} from "./chunk-R7FP73MH.mjs";
import {
Skeleton,
SkeletonCircle,
SkeletonRounded
} from "./chunk-NKVUUWCA.mjs";
import {
ProgressCircle_default
} from "./chunk-5ZVOSDX4.mjs";
import {
ProgressBar_default
} from "./chunk-LDBWF6EA.mjs";
import {
Modal_default
} from "./chunk-TNLGS7SB.mjs";
import {
Text_default
} from "./chunk-IMCIR6TJ.mjs";
import {
cn
} from "./chunk-53ICLDGS.mjs";
// src/components/StudentLessonProgressModal/StudentLessonProgressModal.tsx
import { useMemo, useState } from "react";
import {
MagnifyingGlassIcon,
XCircleIcon,
MedalIcon,
SealWarningIcon
} from "@phosphor-icons/react";
import { CaretRightIcon } from "@phosphor-icons/react/dist/csr/CaretRight";
import { jsx, jsxs } from "react/jsx-runtime";
var ContentAccordionItem = ({
item,
noDataMessage
}) => {
const hasNoData = item.progress === 0 && !item.isCompleted;
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-4 border-t border-border-50", children: [
/* @__PURE__ */ jsx(Text_default, { size: "sm", className: "text-text-950", children: item.content.name }),
hasNoData ? /* @__PURE__ */ jsx(Text_default, { size: "xs", className: "text-text-500", children: noDataMessage }) : /* @__PURE__ */ jsxs(
Text_default,
{
size: "xs",
weight: "medium",
className: "text-text-500 whitespace-nowrap",
children: [
Math.round(item.progress),
"%"
]
}
)
] });
};
var SubtopicAccordionItem = ({
item,
noDataMessage
}) => {
const [isExpanded, setIsExpanded] = useState(false);
const hasChildren = item.contents && item.contents.length > 0;
const hasNoData = item.status === "no_data";
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
/* @__PURE__ */ jsxs(
"button",
{
type: "button",
onClick: () => hasChildren && setIsExpanded(!isExpanded),
disabled: !hasChildren,
className: cn(
"w-full flex items-center justify-between gap-3 p-4 text-left transition-colors duration-200",
"focus:outline-none focus:ring-2 focus:ring-primary-950 focus:ring-inset rounded-xl",
"border-t border-border-50",
hasChildren && "cursor-pointer hover:bg-background-50",
!hasChildren && "cursor-default"
),
"aria-expanded": hasChildren ? isExpanded : void 0,
children: [
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between flex-1 min-w-0", children: [
/* @__PURE__ */ jsx(Text_default, { size: "md", weight: "medium", className: "text-text-950", children: item.subtopic.name }),
!hasNoData && /* @__PURE__ */ jsxs(
Text_default,
{
size: "xs",
weight: "medium",
className: "text-text-500 whitespace-nowrap",
children: [
Math.round(item.progress),
"%"
]
}
)
] }),
hasChildren && /* @__PURE__ */ jsx(
CaretRightIcon,
{
size: 20,
className: cn(
"transition-transform duration-200 flex-shrink-0 text-text-700",
isExpanded ? "rotate-90" : "rotate-0"
)
}
)
]
}
),
hasChildren && /* @__PURE__ */ jsx(
"div",
{
"data-testid": `accordion-content-subtopic-${item.subtopic.id}`,
"data-expanded": isExpanded,
className: cn(
"transition-all duration-300 ease-in-out overflow-hidden",
isExpanded ? "max-h-[2000px] opacity-100" : "max-h-0 opacity-0"
),
children: /* @__PURE__ */ jsx("div", { className: "pl-4", children: item.contents.map((content) => /* @__PURE__ */ jsx(
ContentAccordionItem,
{
item: content,
noDataMessage
},
content.content.id
)) })
}
)
] });
};
var TopicAccordionItem = ({
item,
noDataMessage
}) => {
const [isExpanded, setIsExpanded] = useState(false);
const hasChildren = item.subtopics && item.subtopics.length > 0;
const hasNoData = item.status === "no_data";
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
/* @__PURE__ */ jsxs(
"button",
{
type: "button",
onClick: () => hasChildren && setIsExpanded(!isExpanded),
disabled: !hasChildren,
className: cn(
"w-full flex items-center justify-between gap-3 p-4 text-left transition-colors duration-200",
"focus:outline-none focus:ring-2 focus:ring-primary-950 focus:ring-inset rounded-xl",
hasChildren && "cursor-pointer hover:bg-background-50",
!hasChildren && "cursor-default"
),
"aria-expanded": hasChildren ? isExpanded : void 0,
children: [
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 flex-1 min-w-0", children: [
/* @__PURE__ */ jsx(Text_default, { size: "lg", weight: "bold", className: "text-text-950", children: item.topic.name }),
hasNoData ? /* @__PURE__ */ jsx(Text_default, { size: "xs", className: "text-text-500", children: noDataMessage }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-row items-center gap-2", children: [
/* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
ProgressBar_default,
{
value: item.progress,
variant: "green",
size: "medium"
}
) }),
/* @__PURE__ */ jsxs(
Text_default,
{
size: "xs",
weight: "medium",
className: "text-text-950 whitespace-nowrap",
children: [
Math.round(item.progress),
"%"
]
}
)
] })
] }),
hasChildren && /* @__PURE__ */ jsx(
CaretRightIcon,
{
size: 20,
className: cn(
"transition-transform duration-200 flex-shrink-0 text-text-700",
isExpanded ? "rotate-90" : "rotate-0"
)
}
)
]
}
),
hasChildren && /* @__PURE__ */ jsx(
"div",
{
"data-testid": `accordion-content-${item.topic.id}`,
"data-expanded": isExpanded,
className: cn(
"transition-all duration-300 ease-in-out overflow-hidden",
isExpanded ? "max-h-[2000px] opacity-100" : "max-h-0 opacity-0"
),
children: /* @__PURE__ */ jsx("div", { className: "pl-4", children: item.subtopics.map((subtopic) => /* @__PURE__ */ jsx(
SubtopicAccordionItem,
{
item: subtopic,
noDataMessage
},
subtopic.subtopic.id
)) })
}
)
] });
};
var LoadingSkeleton = () => /* @__PURE__ */ jsxs("div", { "data-testid": "lesson-progress-skeleton", className: "flex flex-col gap-4", children: [
/* @__PURE__ */ jsx(Skeleton, { variant: "text", width: "12rem", height: 24 }),
/* @__PURE__ */ jsxs("div", { className: "flex flex-row gap-3", children: [
/* @__PURE__ */ jsx(SkeletonCircle, { width: 107, height: 107 }),
/* @__PURE__ */ jsx(SkeletonRounded, { className: "flex-1", height: 107 }),
/* @__PURE__ */ jsx(SkeletonRounded, { className: "flex-1", height: 107 })
] }),
/* @__PURE__ */ jsx(Skeleton, { variant: "text", width: "9rem", height: 24, className: "mt-4" }),
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
/* @__PURE__ */ jsx(SkeletonRounded, { height: 80 }),
/* @__PURE__ */ jsx(SkeletonRounded, { height: 80 }),
/* @__PURE__ */ jsx(SkeletonRounded, { height: 80 })
] })
] });
var ErrorContent = ({
message,
prefix
}) => /* @__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: prefix ? `${prefix}: ${message}` : message })
] });
var ProgressContent = ({
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(
MagnifyingGlassIcon,
{
size: 14,
className: "text-primary-800",
weight: "bold"
}
)
}
),
/* @__PURE__ */ jsx(Text_default, { size: "md", className: "text-text-950", children: data.name })
] }),
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-3", children: [
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(
ProgressCircle_default,
{
value: data.overallCompletionRate,
variant: "green",
size: "small",
label: labels.completionRateLabel,
showPercentage: true
}
) }),
/* @__PURE__ */ jsx(
CardActivitiesResults,
{
icon: /* @__PURE__ */ jsx(MedalIcon, { size: 16, weight: "regular", className: "text-text-950" }),
title: labels.bestResultLabel,
subTitle: data.bestResult || "-",
header: "",
action: "success"
}
),
/* @__PURE__ */ jsx(
CardActivitiesResults,
{
icon: /* @__PURE__ */ jsx(SealWarningIcon, { size: 16, weight: "regular", className: "text-white" }),
title: labels.biggestDifficultyLabel,
subTitle: data.biggestDifficulty || "-",
header: "",
action: "error"
}
)
] }),
data.lessonProgress.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.lessonProgressTitle }),
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: data.lessonProgress.map((topic) => /* @__PURE__ */ jsx(
"div",
{
"data-testid": `lesson-item-${topic.topic.id}`,
className: "bg-background rounded-xl border border-border-50",
children: /* @__PURE__ */ jsx(
TopicAccordionItem,
{
item: topic,
noDataMessage: labels.noDataMessage
}
)
},
topic.topic.id
)) })
] })
] });
var renderModalContent = (loading, error, data, labels) => {
if (loading) {
return /* @__PURE__ */ jsx(LoadingSkeleton, {});
}
if (error) {
return /* @__PURE__ */ jsx(ErrorContent, { message: error, prefix: labels.errorMessagePrefix });
}
if (data) {
return /* @__PURE__ */ jsx(ProgressContent, { data, labels });
}
return null;
};
var StudentLessonProgressModal = ({
isOpen,
onClose,
data,
loading = false,
error = null,
labels: customLabels
}) => {
const labels = useMemo(
() => ({ ...DEFAULT_LESSON_PROGRESS_LABELS, ...customLabels }),
[customLabels]
);
const content = renderModalContent(loading, error, data, labels);
if (!content) {
return null;
}
return /* @__PURE__ */ jsx(
Modal_default,
{
isOpen,
onClose,
title: labels.title,
size: "lg",
contentClassName: "max-h-[80vh] overflow-y-auto",
children: content
}
);
};
var StudentLessonProgressModal_default = StudentLessonProgressModal;
export {
StudentLessonProgressModal,
StudentLessonProgressModal_default
};
//# sourceMappingURL=chunk-PTEOS4NY.mjs.map