analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
1,709 lines (1,690 loc) • 708 kB
JavaScript
import {
renderSubjectCell
} from "./chunk-4CJLURKO.mjs";
import {
mapSubjectNameToEnum
} from "./chunk-GVGQ7EUU.mjs";
import {
PERIOD_TABS
} from "./chunk-NPDKLMTS.mjs";
import {
TypeSelector_default
} from "./chunk-Z7PV3KSQ.mjs";
import {
createActivityCategoryConfig
} from "./chunk-3SHJQQCA.mjs";
import {
EXAM_STATUS_OPTIONS
} from "./chunk-P7FCUXDE.mjs";
import {
AreaKnowledgeSelector,
ESSAY_AREA_ID,
GeneralOverviewSection,
PERFORMANCE_TAG_TO_BADGE_ACTION,
SIMULATED_PERFORMANCE_TAG_CONFIG,
SimulatedStudentDetailsModal,
isClassesData,
isMunicipalitiesData,
isStudentsData
} from "./chunk-XEYCESHY.mjs";
import {
useModulesStore
} from "./chunk-KSJOLTXH.mjs";
import {
PeriodSelector
} from "./chunk-I3TCUZIY.mjs";
import {
AnswerSheetCard,
CardContainer,
PageContainer as PageContainer2,
PrintStyles
} from "./chunk-OWNZKDMR.mjs";
import {
examsTableColumns
} from "./chunk-5SP2WHVJ.mjs";
import {
renderTextCell
} from "./chunk-RL26IDPE.mjs";
import {
areSelectedIdsEqual,
calculateFormattedItemsForAutoSelection,
getBadgeText,
handleAccordionValueChange,
isCategoryEnabled,
useTableFilter
} from "./chunk-45LJRS7N.mjs";
import {
useAlertFormStore
} from "./chunk-IQEDRSDD.mjs";
import {
questionTypeLabels
} from "./chunk-GRGWBD7V.mjs";
import {
useAuthStore
} from "./chunk-TNOKCEMB.mjs";
import {
createUseActivitiesHistory
} from "./chunk-BMJTQFRE.mjs";
import {
getClassOptionsFromUserData,
getSchoolOptionsFromUserData,
getSchoolYearOptionsFromUserData,
getSubjectOptionsFromUserData,
mergeFilterOptions
} from "./chunk-XRPLT7ML.mjs";
import {
createUseActivityModels
} from "./chunk-F44EAWVH.mjs";
import {
ACTIVITY_FILTER_STATUS_OPTIONS,
getActivityStatusBadgeAction
} from "./chunk-DJG7DLCI.mjs";
import {
createUseRecommendedLessonsHistory
} from "./chunk-KP6KKVAB.mjs";
import {
formatTime,
loadCategoriesData,
useDynamicStudentFetching
} from "./chunk-5WLR5TLU.mjs";
import {
createUseRecommendedClassDrafts,
createUseRecommendedClassModels
} from "./chunk-3DZ6JVFL.mjs";
import {
RECOMMENDED_CLASS_FILTER_STATUS_OPTIONS,
getRecommendedClassStatusBadgeAction
} from "./chunk-FD4UD2X5.mjs";
import {
createUseSimulations
} from "./chunk-37WFJLC5.mjs";
import {
extractStudentsFromCategories,
useSendActivityModalStore
} from "./chunk-MMCTPGXO.mjs";
import {
validateActivityStep,
validateDeadlineStep
} from "./chunk-MSG5POSR.mjs";
import {
ACTIVITY_MODE_OPTIONS,
ACTIVITY_TYPE_OPTIONS,
ActivitySubtype
} from "./chunk-GMYYB6A2.mjs";
import {
Toaster_default,
useToast
} from "./chunk-L2AMPFWU.mjs";
import {
useUrlAuthentication
} from "./chunk-S6C2Q522.mjs";
import {
useApiConfig
} from "./chunk-KMVBJFFX.mjs";
import {
createUseQuestionsList
} from "./chunk-EHORXGFK.mjs";
import {
PageContainer
} from "./chunk-GNLZTQRR.mjs";
import {
VideoPlayer_default
} from "./chunk-5XJWMPI4.mjs";
import {
Whiteboard_default
} from "./chunk-6TUOCZ7Y.mjs";
import {
ImageUpload
} from "./chunk-IPVIZIHN.mjs";
import {
useAuth
} from "./chunk-VQTRDBGR.mjs";
import {
AlertDialog
} from "./chunk-6E2SCKRJ.mjs";
import {
Calendar_default
} from "./chunk-YPQFSNET.mjs";
import {
Stepper_default
} from "./chunk-4QZWLI7Q.mjs";
import {
useMobile
} from "./chunk-GKY77WVA.mjs";
import {
CorrectActivityModal_default,
QUESTION_STATUS,
convertApiResponseToCorrectionData,
getQuestionStatusBadgeConfig,
renderFromMap
} from "./chunk-3UWJRI7S.mjs";
import {
StatCard
} from "./chunk-3ZYHNRVG.mjs";
import {
AccordionGroup
} from "./chunk-ILCBSWZF.mjs";
import {
ToastStore_default
} from "./chunk-OAP6DJKU.mjs";
import {
CardAccordation
} from "./chunk-2ACDTDO4.mjs";
import {
highlightSearchTerm,
normalizeText,
stripHtmlTags
} from "./chunk-C6FDFF3W.mjs";
import {
prependLetterToHtml
} from "./chunk-DDZDNGBU.mjs";
import {
AlternativesList
} from "./chunk-TUJ3CWS2.mjs";
import {
MultipleChoiceList
} from "./chunk-PZ2H7EXH.mjs";
import {
HtmlMathRenderer_default,
stripHtml
} from "./chunk-FN4G43WK.mjs";
import {
CardAudio
} from "./chunk-R7FP73MH.mjs";
import {
TextArea_default
} from "./chunk-LI2FS7M2.mjs";
import {
Toast_default
} from "./chunk-YGF3KVWG.mjs";
import {
TruncatedText
} from "./chunk-2P7LJCTW.mjs";
import {
Menu,
MenuContent,
MenuItem,
MenuOverflow,
Menu_default
} from "./chunk-WI3GQX74.mjs";
import {
RadioGroup,
RadioGroupItem,
Radio_default
} from "./chunk-NLK3GG73.mjs";
import {
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
Select_default
} from "./chunk-UU7Q5S52.mjs";
import {
TableBody,
TableCell,
TableHead,
TableRow,
Table_default,
useTableSort
} from "./chunk-66F2QDAX.mjs";
import {
EmptyState_default
} from "./chunk-6WVHF7N3.mjs";
import {
Skeleton,
SkeletonCard,
SkeletonRounded,
SkeletonTable,
SkeletonText
} from "./chunk-NKVUUWCA.mjs";
import {
TablePagination_default
} from "./chunk-JYLO3IQT.mjs";
import {
SimplePieChart
} from "./chunk-Y4MZ2KAU.mjs";
import {
ProgressBar_default
} from "./chunk-LDBWF6EA.mjs";
import {
IconButton_default
} from "./chunk-LGQNMQOT.mjs";
import {
IconRender_default
} from "./chunk-QEZJZHJG.mjs";
import {
Input_default
} from "./chunk-EXVVHZOO.mjs";
import {
LatexRenderer_default
} from "./chunk-NNUCT5IL.mjs";
import {
getSubjectInfo
} from "./chunk-3ERLYM6Y.mjs";
import {
Search_default
} from "./chunk-YMDK7D7Z.mjs";
import {
Alert_default
} from "./chunk-YQTOSHD5.mjs";
import {
Badge_default
} from "./chunk-OEW3ST4F.mjs";
import {
CheckBox_default
} from "./chunk-VDUO65VK.mjs";
import {
Chips_default
} from "./chunk-TVFP3HZX.mjs";
import {
Divider_default
} from "./chunk-VN4ORBHU.mjs";
import {
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
DropdownMenu_default
} from "./chunk-DHHHYBOU.mjs";
import {
useTheme
} from "./chunk-HYVBZ5EV.mjs";
import {
SelectionButton_default
} from "./chunk-W46HZ2AP.mjs";
import {
Modal_default
} from "./chunk-TNLGS7SB.mjs";
import {
Button_default
} from "./chunk-LAYB7IKW.mjs";
import {
Text_default
} from "./chunk-IMCIR6TJ.mjs";
import {
areFiltersEqual,
arraysEqual,
cn,
deriveYearIdsFromBankIds,
formatPercentageRounded,
formatScore,
getSelectedIdsFromCategories,
getSubjectColorWithOpacity,
mapQuestionTypeToEnum,
mapQuestionTypeToEnumRequired,
mergeYearIdsForSelectedBanks,
toggleArrayItem,
toggleSingleValue
} from "./chunk-53ICLDGS.mjs";
import {
formatActivityDateToBrazilian,
formatDateToBrazilian,
formatQuestionNumbers,
formatTimeSpent,
getStatusBadgeConfig
} from "./chunk-YG7W6JE3.mjs";
import {
STUDENT_ACTIVITY_STATUS
} from "./chunk-AYI25BJ2.mjs";
import {
GenericApiStatus,
GenericDisplayStatus
} from "./chunk-DG76FRXG.mjs";
import {
QUESTION_TYPE
} from "./chunk-G7IP4VLI.mjs";
// src/components/CheckBoxGroup/CheckBoxGroup.tsx
import { useEffect as useEffect44, useMemo as useMemo43, useRef as useRef35, useState as useState46 } from "react";
// src/components/AlertManager/AlertsManager.tsx
import {
useState as useState3,
useEffect as useEffect5,
useMemo as useMemo4,
useCallback as useCallback2,
useSyncExternalStore,
useRef as useRef3
} from "react";
import { CaretLeftIcon as CaretLeftIcon2 } from "@phosphor-icons/react/dist/csr/CaretLeft";
import { CaretRightIcon } from "@phosphor-icons/react/dist/csr/CaretRight";
import { PaperPlaneTiltIcon as PaperPlaneTiltIcon2 } from "@phosphor-icons/react/dist/csr/PaperPlaneTilt";
// src/components/AlertManager/AlertSteps/MessageStep.tsx
import { useState } from "react";
import { useShallow } from "zustand/react/shallow";
import { jsx, jsxs } from "react/jsx-runtime";
var ACCEPTED_IMAGE_EXTENSIONS = ".jpg,.jpeg,.png,.gif,.webp,.svg";
var MAX_IMAGE_SIZE_BYTES = 5 * 1024 * 1024;
var MAX_IMAGE_SIZE_LABEL = "5MB";
var MessageStep = ({
labels,
allowImageAttachment = true
}) => {
const [imageError, setImageError] = useState(null);
const { title, message, image, setTitle, setMessage, setImage } = useAlertFormStore(
useShallow((state) => ({
title: state.title,
message: state.message,
image: state.image,
setTitle: state.setTitle,
setMessage: state.setMessage,
setImage: state.setImage
}))
);
const handleFileSelect = (file) => {
setImageError(null);
setImage(file);
};
const handleRemoveFile = () => {
setImageError(null);
setImage(null);
};
const handleTypeError = () => {
setImageError(
"Formato de imagem n\xE3o suportado. Use jpg, jpeg, png, gif, webp ou svg."
);
};
const handleSizeError = () => {
setImageError(
`Imagem muito grande. O tamanho m\xE1ximo permitido \xE9 ${MAX_IMAGE_SIZE_LABEL}.`
);
};
const isImageFile = image instanceof File;
return /* @__PURE__ */ jsxs("section", { className: "flex flex-col gap-4", children: [
/* @__PURE__ */ jsx(
Input_default,
{
required: true,
label: labels?.titleLabel || "T\xEDtulo",
placeholder: labels?.titlePlaceholder || "Digite o t\xEDtulo do aviso",
variant: "rounded",
value: title,
onChange: (e) => setTitle(e.target.value)
}
),
/* @__PURE__ */ jsx(
TextArea_default,
{
required: true,
label: labels?.messageLabel || "Mensagem",
placeholder: labels?.messagePlaceholder || "Digite a mensagem do aviso",
value: message,
onChange: (e) => setMessage(e.target.value)
}
),
allowImageAttachment && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
/* @__PURE__ */ jsx(
ImageUpload,
{
selectedFile: isImageFile ? image : null,
onFileSelect: handleFileSelect,
onRemoveFile: handleRemoveFile,
accept: ACCEPTED_IMAGE_EXTENSIONS,
maxSize: MAX_IMAGE_SIZE_BYTES,
onTypeError: handleTypeError,
onSizeError: handleSizeError
}
),
imageError && /* @__PURE__ */ jsx(Text_default, { size: "sm", className: "text-error-600", role: "alert", children: imageError })
] })
] });
};
// src/components/AlertManager/AlertSteps/RecipientsStep.tsx
import { useEffect, useMemo } from "react";
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
var RecipientsStep = ({
categories,
labels,
onCategoriesChange
}) => {
const { recipientCategories, initializeCategory } = useAlertFormStore();
useEffect(() => {
for (const category of categories) {
const existingCategory = recipientCategories[category.key];
if (!existingCategory) {
initializeCategory({
key: category.key,
label: category.label,
availableItems: category.itens || [],
selectedIds: category.selectedIds || [],
allSelected: false
});
}
}
}, [categories, recipientCategories, initializeCategory]);
const handleCategoriesChange = (updatedCategories) => {
for (const category of updatedCategories) {
const selectedIds = category.selectedIds || [];
const allSelected = selectedIds.length === (category.itens?.length || 0);
initializeCategory({
key: category.key,
label: category.label,
availableItems: category.itens || [],
selectedIds,
allSelected
});
}
if (onCategoriesChange) {
onCategoriesChange(updatedCategories);
}
};
const syncedCategories = useMemo(() => {
return categories.map((category) => {
const storeCategory = recipientCategories[category.key];
if (storeCategory) {
return {
...category,
selectedIds: storeCategory.selectedIds
};
}
return category;
});
}, [categories, recipientCategories]);
return /* @__PURE__ */ jsxs2("section", { className: "flex flex-col gap-4", children: [
/* @__PURE__ */ jsx2(Text_default, { size: "lg", weight: "medium", className: "text-text-950", children: labels?.recipientsDescription || "Para quem voc\xEA vai enviar o aviso?" }),
/* @__PURE__ */ jsx2(
CheckboxGroup,
{
categories: syncedCategories,
onCategoriesChange: handleCategoriesChange
}
)
] });
};
// src/components/AlertManager/AlertSteps/DateStep.tsx
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
var DateStep = ({
labels,
allowScheduling = true,
allowEmailCopy = true
}) => {
const date = useAlertFormStore((state) => state.date);
const time = useAlertFormStore((state) => state.time);
const sendToday = useAlertFormStore((state) => state.sendToday);
const sendCopyToEmail = useAlertFormStore((state) => state.sendCopyToEmail);
const setDate = useAlertFormStore((state) => state.setDate);
const setTime = useAlertFormStore((state) => state.setTime);
const setSendToday = useAlertFormStore((state) => state.setSendToday);
const setSendCopyToEmail = useAlertFormStore(
(state) => state.setSendCopyToEmail
);
return /* @__PURE__ */ jsxs3("section", { className: "flex flex-col gap-4", children: [
/* @__PURE__ */ jsxs3("span", { className: "flex flex-row items-center gap-6", children: [
/* @__PURE__ */ jsx3(
Text_default,
{
weight: "normal",
className: "cursor-pointer select-none leading-[150%] flex items-center font-roboto",
children: labels?.sendTodayLabel || "Enviar Hoje?"
}
),
/* @__PURE__ */ jsx3(
CheckBox_default,
{
label: "Sim",
checked: sendToday,
onChange: (e) => setSendToday(e.target.checked)
}
)
] }),
allowScheduling && /* @__PURE__ */ jsx3(
DateTimeInput_default,
{
label: labels?.dateLabel || "Data de envio",
date,
time,
onDateChange: setDate,
onTimeChange: setTime,
disabled: sendToday,
timeLabel: labels?.timeLabel || "Hora de envio",
testId: "alert-datetime"
}
),
allowEmailCopy && /* @__PURE__ */ jsx3(
CheckBox_default,
{
label: labels?.sendCopyToEmailLabel || "Enviar c\xF3pia para e-mail",
checked: sendCopyToEmail,
onChange: (e) => setSendCopyToEmail(e.target.checked)
}
)
] });
};
// src/components/AlertManager/AlertSteps/PreviewStep.tsx
import { useMemo as useMemo2, useEffect as useEffect2 } from "react";
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
var PreviewStep = ({ imageLink, defaultImage }) => {
const title = useAlertFormStore((state) => state.title);
const message = useAlertFormStore((state) => state.message);
const image = useAlertFormStore((state) => state.image);
const imageUrl = useMemo2(() => {
if (globalThis.window === void 0) {
return void 0;
}
if (image instanceof File) {
return globalThis.window.URL.createObjectURL(image);
}
if (typeof image === "string") {
return image;
}
return void 0;
}, [image]);
useEffect2(() => {
return () => {
if (globalThis.window !== void 0 && imageUrl && image instanceof File) {
URL.revokeObjectURL(imageUrl);
}
};
}, [imageUrl, image]);
const finalImageUrl = imageLink || imageUrl || defaultImage || void 0;
return /* @__PURE__ */ jsx4("section", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxs4("div", { className: "bg-background-50 px-5 py-6 flex flex-col items-center gap-4 rounded-xl", children: [
finalImageUrl && /* @__PURE__ */ jsx4("img", { src: finalImageUrl, alt: title || "Imagem do alerta" }),
/* @__PURE__ */ jsxs4("div", { className: "flex flex-col items-center text-center gap-3", children: [
/* @__PURE__ */ jsx4(Text_default, { size: "lg", weight: "semibold", children: title || "Nenhum T\xEDtulo de Alerta" }),
/* @__PURE__ */ jsx4(Text_default, { size: "sm", weight: "normal", className: "text-text-500", children: message || "Aqui aparecer\xE1 a mensagem do alerta definido pelo usu\xE1rio" })
] })
] }) });
};
// src/components/AlertManager/validation.ts
var BASE_STEPS_COUNT = 4;
var validateMessageStep = (formData) => {
if (!formData.title?.trim()) return "T\xEDtulo \xE9 obrigat\xF3rio";
if (!formData.message?.trim()) return "Mensagem \xE9 obrigat\xF3ria";
return true;
};
var validateRecipientsStep = (categories) => {
if (categories.length === 0) return "Nenhuma categoria configurada";
const lastCategory = categories[categories.length - 1];
if (!lastCategory?.selectedIds?.length) return "Selecione destinat\xE1rios";
return true;
};
var validateDateStep = (formData) => {
if (formData.sendToday) return true;
if (!formData.date) return "Data \xE9 obrigat\xF3ria";
if (!formData.time) return "Hora \xE9 obrigat\xF3ria";
return true;
};
var canFinish = (formData, categories) => {
return validateMessageStep(formData) === true && validateRecipientsStep(categories) === true && validateDateStep(formData) === true;
};
var isCurrentStepValid = (currentStep, formData, categories, customSteps) => {
return validateCurrentStep(currentStep, formData, categories, customSteps) === true;
};
var validateCurrentStep = (currentStep, formData, categories, customSteps) => {
switch (currentStep) {
case 0:
return validateMessageStep(formData);
case 1:
return validateRecipientsStep(categories);
case 2:
return validateDateStep(formData);
case 3:
return true;
default: {
const currentStepConfig = customSteps?.[currentStep - BASE_STEPS_COUNT];
return currentStepConfig?.validate ? currentStepConfig.validate(formData) : true;
}
}
};
var advanceToNextStep = (currentStep, completedSteps, setCompletedSteps, setCurrentStep) => {
if (setCompletedSteps && !completedSteps.includes(currentStep)) {
setCompletedSteps([...completedSteps, currentStep]);
}
if (setCurrentStep) {
setCurrentStep(currentStep + 1);
}
};
var handleNext = ({
currentStep,
steps,
formData,
categories,
customSteps,
completedSteps = [],
setCompletedSteps,
setCurrentStep
}) => {
if (currentStep >= steps.length - 1) {
return { success: false, error: "J\xE1 est\xE1 no \xFAltimo step" };
}
const validation = validateCurrentStep(
currentStep,
formData,
categories,
customSteps
);
if (validation !== true) {
console.error("Valida\xE7\xE3o falhou:", validation);
const errorMessage = typeof validation === "string" ? validation : "Preencha todos os campos obrigat\xF3rios";
return { success: false, error: errorMessage };
}
advanceToNextStep(
currentStep,
completedSteps,
setCompletedSteps,
setCurrentStep
);
return { success: true };
};
// src/components/shared/SendModalBase/utils/applyChainedAutoSelection.ts
function applyChainedAutoSelection(categories) {
let current = categories;
let safety = 0;
let changed = true;
while (changed && safety < categories.length + 2) {
safety += 1;
changed = false;
const next = current.map((category) => {
const filteredItems = calculateFormattedItemsForAutoSelection(
category,
current
);
const hasNoSelection = !category.selectedIds || category.selectedIds.length === 0;
if (filteredItems.length === 1 && hasNoSelection) {
changed = true;
return { ...category, selectedIds: [filteredItems[0].id] };
}
return category;
});
current = next;
}
return current;
}
// src/components/shared/SendModalBase/hooks/useDateTimeHandlers.ts
import { useCallback } from "react";
function useDateTimeHandlers({ setFormData }) {
const handleStartDateChange = useCallback(
(value) => {
setFormData({ startDate: value });
},
[setFormData]
);
const handleStartTimeChange = useCallback(
(value) => {
setFormData({ startTime: value });
},
[setFormData]
);
const handleFinalDateChange = useCallback(
(value) => {
setFormData({ finalDate: value });
},
[setFormData]
);
const handleFinalTimeChange = useCallback(
(value) => {
setFormData({ finalTime: value });
},
[setFormData]
);
return {
handleStartDateChange,
handleStartTimeChange,
handleFinalDateChange,
handleFinalTimeChange
};
}
// src/components/shared/SendModalBase/hooks/useCategoryInitialization.ts
import { useEffect as useEffect3, useRef } from "react";
function useCategoryInitialization({
isOpen,
initialCategories,
setCategories,
onCategoriesChange
}) {
const categoriesInitialized = useRef(false);
useEffect3(() => {
if (isOpen && initialCategories.length > 0 && !categoriesInitialized.current) {
const autoSelectedCategories = applyChainedAutoSelection(initialCategories);
setCategories(autoSelectedCategories);
if (onCategoriesChange) {
onCategoriesChange(autoSelectedCategories);
}
categoriesInitialized.current = true;
}
}, [isOpen, initialCategories, setCategories, onCategoriesChange]);
useEffect3(() => {
if (!isOpen) {
categoriesInitialized.current = false;
}
}, [isOpen]);
return {
categoriesInitializedRef: categoriesInitialized
};
}
// src/components/shared/SendModalBase/hooks/useCategorySync.ts
import { useEffect as useEffect4 } from "react";
var DYNAMIC_KEYS = ["turma", "students"];
function dynamicItemsSignature(categories) {
return DYNAMIC_KEYS.map((key) => {
const category = categories.find((c) => c.key === key);
const ids = (category?.itens ?? []).map((item) => item.id).join(",");
return `${key}:${ids}`;
}).join("|");
}
function useCategorySync({
isOpen,
initialCategories,
storeCategories,
setCategories,
categoriesInitializedRef
}) {
useEffect4(() => {
if (isOpen && initialCategories.length > 0 && categoriesInitializedRef.current) {
if (dynamicItemsSignature(initialCategories) !== dynamicItemsSignature(storeCategories)) {
setCategories(initialCategories);
}
}
}, [
isOpen,
initialCategories,
storeCategories,
setCategories,
categoriesInitializedRef
]);
}
// src/components/shared/SendModalBase/components/SendModalError.tsx
import { WarningCircleIcon } from "@phosphor-icons/react/dist/csr/WarningCircle";
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
var SendModalError = ({
error,
testId,
className
}) => {
if (!error) return null;
return /* @__PURE__ */ jsxs5(
Text_default,
{
as: "p",
size: "sm",
color: "text-error-600",
className: `flex items-center gap-1 mt-1 ${className || ""}`,
"data-testid": testId,
"aria-live": "polite",
children: [
/* @__PURE__ */ jsx5(WarningCircleIcon, { size: 16 }),
error
]
}
);
};
// src/components/shared/SendModalBase/components/RecipientStep.tsx
import { useMemo as useMemo3 } from "react";
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
var RecipientStep = ({
categories,
onCategoriesChange,
entityNameWithArticle,
studentsError,
testIdPrefix
}) => {
const categoriesWithSearch = useMemo3(
() => categories.map(
(category) => category.key === "students" ? { ...category, searchable: true } : category
),
[categories]
);
return /* @__PURE__ */ jsxs6(
"div",
{
className: "flex flex-col gap-4 min-h-0 flex-1",
"data-testid": testIdPrefix ? `${testIdPrefix}-recipient-step` : void 0,
children: [
/* @__PURE__ */ jsxs6(
Text_default,
{
size: "sm",
weight: "medium",
color: "text-text-700",
className: "flex-shrink-0",
children: [
"Para quem voc\xEA vai enviar ",
entityNameWithArticle,
"?"
]
}
),
/* @__PURE__ */ jsx6(
"div",
{
className: cn(
"flex-1 min-h-0 overflow-y-auto",
"scrollbar-thin scrollbar-thumb-border-300 scrollbar-track-transparent"
),
"data-testid": testIdPrefix ? `${testIdPrefix}-scroll-container` : "scroll-container",
children: /* @__PURE__ */ jsx6(
CheckboxGroup,
{
categories: categoriesWithSearch,
onCategoriesChange,
compactSingleItem: true,
showDivider: true
}
)
}
),
/* @__PURE__ */ jsx6(
SendModalError,
{
error: studentsError,
testId: testIdPrefix ? `${testIdPrefix}-students-error` : void 0,
className: "flex-shrink-0"
}
)
]
}
);
};
// src/components/DateTimeInput/DateTimeInput.tsx
import { useRef as useRef2, useState as useState2 } from "react";
import { CalendarBlankIcon } from "@phosphor-icons/react/dist/csr/CalendarBlank";
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
var formatDateToInput = (dateObj) => {
const year = dateObj.getFullYear();
const month = String(dateObj.getMonth() + 1).padStart(2, "0");
const day = String(dateObj.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
};
var DateTimeInput = ({
label,
date,
time,
onDateChange,
onTimeChange,
errorMessage,
disabled = false,
defaultTime = "00:00",
testId,
timeLabel = "Hora",
className
}) => {
const [isCalendarOpen, setIsCalendarOpen] = useState2(false);
const [selectedDate, setSelectedDate] = useState2(
date ? /* @__PURE__ */ new Date(`${date}T12:00:00`) : void 0
);
const triggerRef = useRef2(null);
const handleDateSelect = (dateObj) => {
setSelectedDate(dateObj);
onDateChange(formatDateToInput(dateObj));
if (!time) {
onTimeChange(defaultTime);
}
};
const handleDateInputChange = (e) => {
const value = e.target.value;
if (value.includes("T")) {
const [datePart, timePart] = value.split("T");
onDateChange(datePart);
if (timePart) {
onTimeChange(timePart);
}
} else {
onDateChange(value);
}
if (value) {
const dateValue = value.includes("T") ? value : `${value}T12:00:00`;
const dateObj = new Date(dateValue);
if (!Number.isNaN(dateObj.getTime())) {
setSelectedDate(dateObj);
}
}
};
const handleTimeChange = (e) => {
onTimeChange(e.target.value);
};
const inputValue = date ? `${date}T${time || defaultTime}` : "";
return /* @__PURE__ */ jsxs7(
DropdownMenu_default,
{
open: !disabled && isCalendarOpen,
onOpenChange: (open) => {
if (!disabled) {
setIsCalendarOpen(open);
}
},
children: [
/* @__PURE__ */ jsx7(
DropdownMenuTrigger,
{
className,
ref: triggerRef,
disabled,
children: /* @__PURE__ */ jsx7(
Input_default,
{
label,
type: "datetime-local",
placeholder: "00/00/0000",
value: inputValue,
onChange: handleDateInputChange,
variant: "rounded",
errorMessage,
disabled,
"data-testid": testId ? `${testId}-input` : void 0,
iconRight: /* @__PURE__ */ jsx7(CalendarBlankIcon, { size: 14 }),
className: "[&::-webkit-calendar-picker-indicator]:hidden"
}
)
}
),
/* @__PURE__ */ jsxs7(
DropdownMenuContent,
{
align: "start",
className: "p-0 z-[100]",
portal: true,
triggerRef,
children: [
/* @__PURE__ */ jsx7(
Calendar_default,
{
variant: "selection",
selectedDate,
onDateSelect: handleDateSelect,
showActivities: false
}
),
/* @__PURE__ */ jsx7("div", { className: "p-3 border-t border-border-200", children: /* @__PURE__ */ jsx7(
Input_default,
{
label: timeLabel,
type: "time",
value: time || defaultTime,
onChange: handleTimeChange,
variant: "rounded",
"data-testid": testId ? `${testId}-time` : void 0
}
) })
]
}
)
]
}
);
};
var DateTimeInput_default = DateTimeInput;
// src/components/shared/SendModalBase/components/DeadlineStep.tsx
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
var DeadlineStep = ({
startDate,
startTime,
finalDate,
finalTime,
onStartDateChange,
onStartTimeChange,
onFinalDateChange,
onFinalTimeChange,
errors,
testIdPrefix,
children
}) => {
return /* @__PURE__ */ jsxs8(
"div",
{
className: "flex flex-col gap-4 sm:gap-6 pt-6",
"data-testid": testIdPrefix ? `${testIdPrefix}-deadline-step` : void 0,
children: [
/* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-2 sm:grid sm:grid-cols-2", children: [
/* @__PURE__ */ jsx8(
DateTimeInput_default,
{
label: "Iniciar em*",
date: startDate,
time: startTime,
onDateChange: onStartDateChange,
onTimeChange: onStartTimeChange,
errorMessage: [errors.startDate, errors.startTime].filter(Boolean).join(" ") || void 0,
defaultTime: "00:00",
testId: testIdPrefix ? `${testIdPrefix}-start-datetime` : "start-datetime",
className: "w-full"
}
),
/* @__PURE__ */ jsx8(
DateTimeInput_default,
{
label: "Finalizar at\xE9*",
date: finalDate,
time: finalTime,
onDateChange: onFinalDateChange,
onTimeChange: onFinalTimeChange,
errorMessage: [errors.finalDate, errors.finalTime].filter(Boolean).join(" ") || void 0,
defaultTime: "23:59",
testId: testIdPrefix ? `${testIdPrefix}-final-datetime` : "final-datetime",
className: "w-full"
}
)
] }),
children
]
}
);
};
var DeadlineStep_default = DeadlineStep;
// src/components/shared/SendModalBase/components/SendModalFooter.tsx
import { CaretLeftIcon } from "@phosphor-icons/react/dist/csr/CaretLeft";
import { ArrowRightIcon } from "@phosphor-icons/react/dist/csr/ArrowRight";
import { PaperPlaneTiltIcon } from "@phosphor-icons/react/dist/csr/PaperPlaneTilt";
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
var SendModalFooter = ({
currentStep,
maxSteps,
isLoading,
onCancel,
onPreviousStep,
onNextStep,
onSubmit,
entityName,
testIdPrefix
}) => {
const isLastStep = currentStep >= maxSteps;
const showPreviousButton = currentStep > 1;
return /* @__PURE__ */ jsxs9(
"div",
{
className: "flex flex-col-reverse sm:flex-row items-center justify-between gap-3 w-full",
"data-testid": testIdPrefix ? `${testIdPrefix}-footer` : void 0,
children: [
/* @__PURE__ */ jsx9(
Button_default,
{
variant: "link",
action: "primary",
onClick: onCancel,
className: "w-full sm:w-auto",
"data-testid": testIdPrefix ? `${testIdPrefix}-cancel-button` : void 0,
children: "Cancelar"
}
),
/* @__PURE__ */ jsxs9("div", { className: "flex flex-col-reverse sm:flex-row items-center gap-2 sm:gap-3 w-full sm:w-auto", children: [
showPreviousButton && /* @__PURE__ */ jsx9(
Button_default,
{
variant: "outline",
action: "primary",
onClick: onPreviousStep,
iconLeft: /* @__PURE__ */ jsx9(CaretLeftIcon, { size: 16 }),
className: "w-full sm:w-auto",
"data-testid": testIdPrefix ? `${testIdPrefix}-previous-button` : void 0,
children: "Anterior"
}
),
isLastStep ? /* @__PURE__ */ jsx9(
Button_default,
{
variant: "solid",
action: "primary",
onClick: onSubmit,
disabled: isLoading,
iconLeft: /* @__PURE__ */ jsx9(PaperPlaneTiltIcon, { size: 16 }),
className: "w-full sm:w-auto",
"data-testid": testIdPrefix ? `${testIdPrefix}-submit-button` : void 0,
children: isLoading ? "Enviando..." : `Enviar ${entityName}`
}
) : /* @__PURE__ */ jsx9(
Button_default,
{
variant: "solid",
action: "primary",
onClick: onNextStep,
iconRight: /* @__PURE__ */ jsx9(ArrowRightIcon, { size: 16 }),
className: "w-full sm:w-auto",
"data-testid": testIdPrefix ? `${testIdPrefix}-next-button` : void 0,
children: "Pr\xF3ximo"
}
)
] })
]
}
);
};
// src/components/AlertManager/AlertsManager.tsx
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
var StepWrapper = ({ children }) => /* @__PURE__ */ jsx10("div", { children });
var AlertsManager = ({
config,
isOpen = false,
onClose,
imageLink,
defaultImage
}) => {
const [isModalOpen, setIsModalOpen] = useState3(isOpen);
const [currentStep, setCurrentStep] = useState3(0);
const [completedSteps, setCompletedSteps] = useState3([]);
const [categories, setCategories] = useState3(config.categories);
const formData = useSyncExternalStore(
useAlertFormStore.subscribe,
useAlertFormStore.getState
);
useEffect5(() => {
setIsModalOpen(isOpen);
}, [isOpen]);
const categoriesInitializedRef = useRef3(false);
const { labels, behavior, steps: customSteps } = config;
const { handleCategoriesChange: baseHandleCategoriesChange } = useDynamicStudentFetching(setCategories, {
fetchStudentsByFilters: behavior?.fetchStudentsByFilters
});
const handleCategoriesChange = useCallback2(
async (updatedCategories) => {
await baseHandleCategoriesChange(updatedCategories);
},
[baseHandleCategoriesChange]
);
useEffect5(() => {
if (isModalOpen && config.categories.length > 0 && !categoriesInitializedRef.current) {
const autoSelectedCategories = applyChainedAutoSelection(
config.categories
);
setCategories(autoSelectedCategories);
void handleCategoriesChange(autoSelectedCategories);
categoriesInitializedRef.current = true;
}
}, [
isModalOpen,
config.categories,
applyChainedAutoSelection,
handleCategoriesChange
]);
useEffect5(() => {
if (!isModalOpen) {
categoriesInitializedRef.current = false;
}
}, [isModalOpen]);
const defaultSteps = [
{
id: "1",
label: "Mensagem",
state: "completed"
},
{
id: "2",
label: labels?.recipientsTitle || "Destinat\xE1rios",
state: "current"
},
{
id: "3",
label: labels?.dateLabel || "Data de envio",
state: "pending"
},
{
id: "4",
label: labels?.previewTitle || "Pr\xE9via",
state: "pending"
}
];
const steps = customSteps || defaultSteps;
const handleCloseModal = () => {
setIsModalOpen(false);
onClose?.();
};
const isCurrentStepValid2 = useCallback2(() => {
return isCurrentStepValid(
currentStep,
formData,
categories,
customSteps
);
}, [currentStep, categories, customSteps, formData]);
const canFinish2 = useCallback2(() => {
return canFinish(formData, categories);
}, [categories, formData]);
const handleNext2 = useCallback2(() => {
const result = handleNext({
currentStep,
steps,
formData,
categories,
customSteps,
completedSteps,
setCompletedSteps,
setCurrentStep
});
if (!result.success && result.error) {
alert(result.error);
}
}, [
currentStep,
steps,
categories,
customSteps,
completedSteps,
setCompletedSteps,
setCurrentStep,
formData
]);
const handlePrevious = useCallback2(() => {
if (currentStep > 0) {
setCurrentStep(currentStep - 1);
}
}, [currentStep, setCurrentStep]);
const handleFinish = async () => {
if (!completedSteps.includes(currentStep)) {
setCompletedSteps([...completedSteps, currentStep]);
}
const alertData = {
title: formData.title,
message: formData.message,
image: formData.image,
date: formData.date,
time: formData.time,
sendToday: formData.sendToday,
sendCopyToEmail: formData.sendCopyToEmail,
recipientCategories: Object.fromEntries(
Object.entries(formData.recipientCategories).map(([key, c]) => [
key,
{
selectedIds: c.selectedIds || [],
allSelected: !!c.allSelected
}
])
)
};
try {
if (behavior?.onSendAlert) {
await behavior.onSendAlert(alertData);
} else {
console.log("Dados do formul\xE1rio:", alertData);
alert("Aviso enviado com sucesso!");
}
handleCloseModal();
} catch (error) {
console.error("Erro ao enviar aviso:", error);
}
};
const dynamicSteps = steps.map(
(step, index) => {
if (completedSteps.includes(index)) {
return { ...step, state: "completed" };
}
if (index === currentStep) {
return { ...step, state: "current" };
}
return { ...step, state: "pending" };
}
);
const currentStepContent = useMemo4(() => {
if (customSteps?.[currentStep]?.component) {
const CustomComponent = customSteps[currentStep].component;
return /* @__PURE__ */ jsx10(StepWrapper, { children: /* @__PURE__ */ jsx10(CustomComponent, { onNext: handleNext2, onPrevious: handlePrevious }) });
}
switch (currentStep) {
case 0:
return /* @__PURE__ */ jsx10(StepWrapper, { children: /* @__PURE__ */ jsx10(
MessageStep,
{
labels,
allowImageAttachment: behavior?.allowImageAttachment
}
) });
case 1:
return /* @__PURE__ */ jsx10(StepWrapper, { children: /* @__PURE__ */ jsx10(
RecipientsStep,
{
categories,
labels,
onCategoriesChange: handleCategoriesChange
}
) });
case 2:
return /* @__PURE__ */ jsx10(StepWrapper, { children: /* @__PURE__ */ jsx10(
DateStep,
{
labels,
allowScheduling: behavior?.allowScheduling,
allowEmailCopy: behavior?.allowEmailCopy
}
) });
case 3:
return /* @__PURE__ */ jsx10(StepWrapper, { children: /* @__PURE__ */ jsx10(PreviewStep, { imageLink, defaultImage }) });
default:
return null;
}
}, [
currentStep,
customSteps,
categories,
labels,
behavior,
handleNext2,
handlePrevious,
imageLink,
defaultImage
]);
const isFirstStep = currentStep === 0;
const isLastStep = currentStep === steps.length - 1;
return /* @__PURE__ */ jsx10(
Modal_default,
{
isOpen: isModalOpen,
onClose: handleCloseModal,
title: labels?.modalTitle || "Enviar aviso",
size: "md",
contentClassName: "p-0",
footer: /* @__PURE__ */ jsx10("div", { className: "flex gap-3 justify-end w-full", children: /* @__PURE__ */ jsxs10("div", { className: "flex gap-3", children: [
/* @__PURE__ */ jsx10(Button_default, { variant: "link", size: "small", onClick: handleCloseModal, children: labels?.cancelButton || "Cancelar" }),
!isFirstStep && /* @__PURE__ */ jsx10(
Button_default,
{
variant: "outline",
size: "small",
iconLeft: /* @__PURE__ */ jsx10(CaretLeftIcon2, {}),
onClick: handlePrevious,
children: labels?.previousButton || "Anterior"
}
),
isLastStep ? /* @__PURE__ */ jsx10(
Button_default,
{
variant: "solid",
iconLeft: /* @__PURE__ */ jsx10(PaperPlaneTiltIcon2, {}),
size: "small",
onClick: handleFinish,
disabled: !canFinish2(),
children: labels?.finishButton || "Enviar Aviso"
}
) : /* @__PURE__ */ jsx10(
Button_default,
{
variant: "solid",
iconRight: /* @__PURE__ */ jsx10(CaretRightIcon, {}),
size: "small",
onClick: handleNext2,
disabled: !isCurrentStepValid2(),
children: labels?.nextButton || "Pr\xF3ximo"
}
)
] }) }),
children: /* @__PURE__ */ jsxs10("div", { className: "flex flex-col h-[calc(100vh-14rem)] max-h-[600px]", children: [
/* @__PURE__ */ jsx10("div", { className: "shrink-0 px-6 pt-4", children: /* @__PURE__ */ jsx10(
Stepper_default,
{
steps: dynamicSteps,
size: "small",
showProgress: true,
responsive: true,
progressText: `Etapa ${currentStep + 1} de ${steps.length}`
}
) }),
/* @__PURE__ */ jsx10("div", { className: "flex-1 overflow-y-auto px-6 pb-4", children: currentStepContent })
] })
}
);
};
// src/hooks/useActivityFiltersData.ts
import { useState as useState4, useEffect as useEffect6, useCallback as useCallback3, useMemo as useMemo5, useRef as useRef4 } from "react";
var areCategoriesSame = (prev, current) => {
if (prev.length !== current.length) return false;
return current.every((category) => {
const prevCategory = prev.find((c) => c.key === category.key);
if (!prevCategory) return false;
const prevIds = (prevCategory.itens || []).map(
(item) => item.id
);
const currentIds = (category.itens || []).map(
(item) => item.id
);
if (prevIds.length !== currentIds.length) return false;
return currentIds.every((id) => prevIds.includes(id));
});
};
var mergeCategoriesWithSelection = (prev, current) => {
return current.map((category) => {
const prevCategory = prev.find((c) => c.key === category.key);
if (!prevCategory) {
return category;
}
const validSelectedIds = (prevCategory.selectedIds || []).filter(
(id) => category.itens?.some((item) => item.id === id)
);
return {
...category,
selectedIds: validSelectedIds
};
});
};
var mapSelectedNames = (ids, items) => {
return ids.map((id) => {
const item = items.find((t) => t.id === id);
return item ? item.name : null;
}).filter((name) => name !== null);
};
var useActivityFiltersDataImpl = (apiClient, options) => {
const { selectedSubjects, institutionId } = options;
const [banksState, setBanksState] = useState4({
banks: [],
bankYears: [],
loading: false,
error: null
});
const loadBanks = useCallback3(async () => {
setBanksState((prev) => ({ ...prev, loading: true, error: null }));
try {
const response = await apiClient.get(
"/questions/exam-institutions"
);
const banksMap = /* @__PURE__ */ new Map();
const bankYearsArray = [];
for (const item of response.data.data) {
if (!item.questionBankName) continue;
const existingBank = banksMap.get(item.questionBankName);
if (existingBank) {
if (!existingBank.years.includes(item.year)) {
existingBank.years.push(item.year);
}
existingBank.questionsCount += item.questionsCount;
} else {
banksMap.set(item.questionBankName, {
id: item.questionBankName,
name: item.questionBankName,
examInstitution: item.questionBankName,
years: [item.year],
questionsCount: item.questionsCount
});
}
bankYearsArray.push({
id: `${item.questionBankYearId}-${item.questionBankName}`,
name: item.year,
bankId: item.questionBankName
});
}
const banks = Array.from(banksMap.values()).map((bank) => ({
id: bank.id,
name: bank.name,
examInstitution: bank.examInstitution
}));
setBanksState({
banks,
bankYears: bankYearsArray,
loading: false,
error: null
});
} catch (error) {
console.error("Erro ao carregar bancas de vestibular:", error);
setBanksState((prev) => ({
...prev,
loading: false,
error: "Erro ao carregar bancas de vestibular"
}));
}
}, [apiClient]);
const [areasState, setAreasState] = useState4({
knowledgeAreas: [],
loading: false,
error: null
});
const loadKnowledgeAreas = useCallback3(async () => {
setAreasState((prev) => ({ ...prev, loading: true, error: null }));
try {
const response = await apiClient.get(
"/knowledge/subjects"
);
setAreasState({
knowledgeAreas: response.data.data,
loading: false,
error: null
});
} catch (error) {
console.error("Erro ao carregar \xE1reas de conhecimento:", error);
setAreasState((prev) => ({
...prev,
loading: false,
error: "Erro ao carregar \xE1reas de conhecimento"
}));
}
}, [apiClient]);
const [questionTypesState, setQuestionTypesState] = useState4({
questionTypes: [],
loading: false,
error: null
});
const loadQuestionTypes = useCallback3(async () => {
if (!institutionId) {
setQuestionTypesState((prev) => ({
...prev,
questionTypes: [],
loading: false,
error: null
}));
return;
}
setQuestionTypesState((prev) => ({
...prev,
loading: true,
error: null
}));
try {
const response = await apiClient.get(
`/institutions/${institutionId}/question-types`
);
const mappedTypes = response.data.data.questionTypes.map((type) => mapQuestionTypeToEnum(type)).filter((type) => type !== null);
setQuestionTypesState({
questionTypes: mappedTypes,
loading: false,
error: null
});
} catch (error) {
console.error("Erro ao carregar tipos de quest\xF5es:", error);
setQuestionTypesState((prev) => ({
...prev,
loading: false,
error: "Erro ao carregar tipos de quest\xF5es"
}));
}
}, [apiClient, institutionId]);
const [knowledgeStructure, setKnowledgeStructure] = useState4({
topics: [],
subtopics: [],
contents: [],
loading: false,
error: null
});
const [knowledgeCategories, setKnowledgeCategories] = useState4([]);
const previousSubjectsRef = useRef4(null);
const loadTopics = useCallback3(
async (subjectIds) => {
if (subjectIds.length === 0) {
setKnowledgeStructure({
topics: [],
subtopics: [],
contents: [],
loading: false,
error: null
});
setKnowledgeCategories([]);
return;
}
setKnowledgeStructure((prev) => ({
...prev,
loading: true,
error: null
}));
try {
const response = await apiClient.post(
"/knowledge/topics",
{ subjectIds }
);
const topics = response.data.data.map((topic) => ({
id: topic.id,
name: topic.name
}));
setKnowledgeStructure((prev) => ({
...prev,
topics,
subtopics: [],
contents: [],
loading: false,
error: null
}));
} catch (error) {
console.error("Erro ao carregar temas:", error);
setKnowledgeStructure((prev) => ({
...prev,
topics: [],
subtopics: [],
contents: [],
loading: false,
error: "Erro ao carregar temas"
}));
}
},
[apiClient]
);
const loadSubtopics = useCallback3(
async (topicIds) => {
if (topicIds.length === 0) {
setKnowledgeStructure((prev) => ({
...prev,
subtopics: [],
contents: [],
loading: false,
error: null
}));
return;
}
setKnowledgeStructure((prev) => ({
...prev,
loading: topicIds.length > 0,
error: null
}));
try {
const response = await apiClient.post(
"/knowledge/subtopics",
{ topicIds }
);
const subtopics = response.data.data.map(
(subtopic) => ({
id: subtopic.id,
name: subtopic.name,
topicId: subtopic.topicId || topicIds[0]
})
);
setKnowledgeStructure((prev) => ({
...prev,
subtopics,
contents: [],
loading: false,
error: null
}));
} catch (error) {
console.error("Erro ao carregar subtemas:", error);
setKnowledgeStructure((prev) => ({
...prev,
subtopics: [],
contents: [],
loading: false,
error: "Erro ao carregar subtemas"
}));
}
},
[apiClient]
);
const loadContents = useCallback3(
async (subtopicIds) => {
if (subtopicIds.length === 0) {
setKnowledgeStructure((prev) => ({
...prev,
contents: [],
loading: false,
error: null
}));
return;
}
setKnowledgeStructure((prev) => ({
...prev,
loading: true,