analytica-frontend-lib 1.0.98 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -40,7 +40,7 @@ export { AuthProvider, ProtectedRoute, PublicRoute, getRootDomain, useAuth, useA
40
40
  export { createZustandAuthAdapter } from './Auth/zustandAuthAdapter/index.mjs';
41
41
  export { useUrlAuthentication } from './Auth/useUrlAuthentication/index.mjs';
42
42
  export { useApiConfig } from './Auth/useApiConfig/index.mjs';
43
- export { Quiz, QuizAlternative, QuizConnectDots, QuizContent, QuizDissertative, QuizFooter, QuizHeader, QuizHeaderResult, QuizListResult, QuizListResultByMateria, QuizMultipleChoice, QuizQuestionList, QuizResultHeaderTitle, QuizResultPerformance, QuizResultTitle, QuizTitle, QuizTrueOrFalse, getStatusBadge } from './Quiz/index.mjs';
43
+ export { Quiz, QuizAlternative, QuizConnectDots, QuizContent, QuizDissertative, QuizFooter, QuizHeader, QuizHeaderResult, QuizImageQuestion, QuizListResult, QuizListResultByMateria, QuizMultipleChoice, QuizQuestionList, QuizResultHeaderTitle, QuizResultPerformance, QuizResultTitle, QuizTitle, QuizTrueOrFalse, getStatusBadge } from './Quiz/index.mjs';
44
44
  export { useQuizStore } from './Quiz/useQuizStore/index.mjs';
45
45
  import 'react/jsx-runtime';
46
46
 
@@ -129,6 +129,6 @@ declare const CheckboxListItem: react.ForwardRefExoticComponent<{
129
129
  state?: CheckboxListState;
130
130
  /** Additional CSS classes */
131
131
  className?: string;
132
- } & Omit<InputHTMLAttributes<HTMLInputElement>, "onChange" | "name" | "type" | "size" | "value" | "checked"> & react.RefAttributes<HTMLInputElement>>;
132
+ } & Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "value" | "checked" | "type" | "name" | "onChange"> & react.RefAttributes<HTMLInputElement>>;
133
133
 
134
134
  export { CheckboxList, CheckboxListItem };
package/dist/index.d.ts CHANGED
@@ -40,7 +40,7 @@ export { AuthProvider, ProtectedRoute, PublicRoute, getRootDomain, useAuth, useA
40
40
  export { createZustandAuthAdapter } from './Auth/zustandAuthAdapter/index.js';
41
41
  export { useUrlAuthentication } from './Auth/useUrlAuthentication/index.js';
42
42
  export { useApiConfig } from './Auth/useApiConfig/index.js';
43
- export { Quiz, QuizAlternative, QuizConnectDots, QuizContent, QuizDissertative, QuizFooter, QuizHeader, QuizHeaderResult, QuizListResult, QuizListResultByMateria, QuizMultipleChoice, QuizQuestionList, QuizResultHeaderTitle, QuizResultPerformance, QuizResultTitle, QuizTitle, QuizTrueOrFalse, getStatusBadge } from './Quiz/index.js';
43
+ export { Quiz, QuizAlternative, QuizConnectDots, QuizContent, QuizDissertative, QuizFooter, QuizHeader, QuizHeaderResult, QuizImageQuestion, QuizListResult, QuizListResultByMateria, QuizMultipleChoice, QuizQuestionList, QuizResultHeaderTitle, QuizResultPerformance, QuizResultTitle, QuizTitle, QuizTrueOrFalse, getStatusBadge } from './Quiz/index.js';
44
44
  export { useQuizStore } from './Quiz/useQuizStore/index.js';
45
45
  import 'react/jsx-runtime';
46
46
 
@@ -129,6 +129,6 @@ declare const CheckboxListItem: react.ForwardRefExoticComponent<{
129
129
  state?: CheckboxListState;
130
130
  /** Additional CSS classes */
131
131
  className?: string;
132
- } & Omit<InputHTMLAttributes<HTMLInputElement>, "onChange" | "name" | "type" | "size" | "value" | "checked"> & react.RefAttributes<HTMLInputElement>>;
132
+ } & Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "value" | "checked" | "type" | "name" | "onChange"> & react.RefAttributes<HTMLInputElement>>;
133
133
 
134
134
  export { CheckboxList, CheckboxListItem };
package/dist/index.js CHANGED
@@ -87,6 +87,7 @@ __export(src_exports, {
87
87
  QuizFooter: () => QuizFooter,
88
88
  QuizHeader: () => QuizHeader,
89
89
  QuizHeaderResult: () => QuizHeaderResult,
90
+ QuizImageQuestion: () => QuizImageQuestion,
90
91
  QuizListResult: () => QuizListResult,
91
92
  QuizListResultByMateria: () => QuizListResultByMateria,
92
93
  QuizMultipleChoice: () => QuizMultipleChoice,
@@ -7585,6 +7586,9 @@ var useQuizStore = (0, import_zustand7.create)()(
7585
7586
  // src/assets/img/simulated-result.png
7586
7587
  var simulated_result_default = "./simulated-result-QN5HCUY5.png";
7587
7588
 
7589
+ // src/assets/img/mock-image-question.png
7590
+ var mock_image_question_default = "./mock-image-question-HEZCLFDL.png";
7591
+
7588
7592
  // src/components/Quiz/Quiz.tsx
7589
7593
  var import_jsx_runtime37 = require("react/jsx-runtime");
7590
7594
  var getStatusBadge = (status) => {
@@ -7723,7 +7727,8 @@ var QuizContent = (0, import_react25.forwardRef)(({ variant, paddingBottom }) =>
7723
7727
  ["DISSERTATIVA" /* DISSERTATIVA */]: QuizDissertative,
7724
7728
  ["VERDADEIRO_FALSO" /* VERDADEIRO_FALSO */]: QuizTrueOrFalse,
7725
7729
  ["LIGAR_PONTOS" /* LIGAR_PONTOS */]: QuizConnectDots,
7726
- ["PREENCHER" /* PREENCHER */]: QuizFill
7730
+ ["PREENCHER" /* PREENCHER */]: QuizFill,
7731
+ ["IMAGEM" /* IMAGEM */]: QuizImageQuestion
7727
7732
  };
7728
7733
  const QuestionComponent = currentQuestion ? questionComponents[currentQuestion.type] : null;
7729
7734
  return QuestionComponent ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(QuestionComponent, { variant, paddingBottom }) : null;
@@ -8263,6 +8268,147 @@ var QuizFill = ({
8263
8268
  ] })
8264
8269
  ] });
8265
8270
  };
8271
+ var QuizImageQuestion = ({
8272
+ variant = "default",
8273
+ paddingBottom
8274
+ }) => {
8275
+ const correctPositionRelative = { x: 0.48, y: 0.45 };
8276
+ const calculateCorrectRadiusRelative = () => {
8277
+ const circleWidthRelative = 0.15;
8278
+ const circleHeightRelative = 0.3;
8279
+ const averageRadius = (circleWidthRelative + circleHeightRelative) / 4;
8280
+ const tolerance = 0.02;
8281
+ return averageRadius + tolerance;
8282
+ };
8283
+ const correctRadiusRelative = calculateCorrectRadiusRelative();
8284
+ const mockUserAnswerRelative = { x: 0.72, y: 0.348 };
8285
+ const [clickPositionRelative, setClickPositionRelative] = (0, import_react25.useState)(variant == "result" ? mockUserAnswerRelative : null);
8286
+ const convertToRelativeCoordinates = (x, y, rect) => {
8287
+ const safeWidth = Math.max(rect.width, 1e-3);
8288
+ const safeHeight = Math.max(rect.height, 1e-3);
8289
+ const xRelative = Math.max(0, Math.min(1, x / safeWidth));
8290
+ const yRelative = Math.max(0, Math.min(1, y / safeHeight));
8291
+ return { x: xRelative, y: yRelative };
8292
+ };
8293
+ const handleImageClick = (event) => {
8294
+ if (variant === "result") return;
8295
+ const rect = event.currentTarget.getBoundingClientRect();
8296
+ const x = event.clientX - rect.left;
8297
+ const y = event.clientY - rect.top;
8298
+ const positionRelative = convertToRelativeCoordinates(x, y, rect);
8299
+ setClickPositionRelative(positionRelative);
8300
+ };
8301
+ const handleKeyboardActivate = () => {
8302
+ if (variant === "result") return;
8303
+ setClickPositionRelative({ x: 0.5, y: 0.5 });
8304
+ };
8305
+ const isCorrect = () => {
8306
+ if (!clickPositionRelative) return false;
8307
+ const distance = Math.sqrt(
8308
+ Math.pow(clickPositionRelative.x - correctPositionRelative.x, 2) + Math.pow(clickPositionRelative.y - correctPositionRelative.y, 2)
8309
+ );
8310
+ return distance <= correctRadiusRelative;
8311
+ };
8312
+ const getUserCircleColorClasses = () => {
8313
+ if (variant === "default") {
8314
+ return "bg-indicator-primary/70 border-[#F8CC2E]";
8315
+ }
8316
+ if (variant === "result") {
8317
+ return isCorrect() ? "bg-success-600/70 border-white" : "bg-indicator-error/70 border-white";
8318
+ }
8319
+ return "bg-success-600/70 border-white";
8320
+ };
8321
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
8322
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(QuizSubTitle, { subTitle: "Clique na \xE1rea correta" }),
8323
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(QuizContainer, { className: cn("", paddingBottom), children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
8324
+ "div",
8325
+ {
8326
+ "data-testid": "quiz-image-container",
8327
+ className: "space-y-6 p-3 relative inline-block",
8328
+ children: [
8329
+ variant == "result" && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
8330
+ "div",
8331
+ {
8332
+ "data-testid": "quiz-legend",
8333
+ className: "flex items-center gap-4 text-xs",
8334
+ children: [
8335
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center gap-2", children: [
8336
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "w-3 h-3 rounded-full bg-indicator-primary/70 border border-[#F8CC2E]" }),
8337
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-text-600 font-medium text-sm", children: "\xC1rea correta" })
8338
+ ] }),
8339
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center gap-2", children: [
8340
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "w-3 h-3 rounded-full bg-success-600/70 border border-white" }),
8341
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-text-600 font-medium text-sm", children: "Resposta correta" })
8342
+ ] }),
8343
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center gap-2", children: [
8344
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "w-3 h-3 rounded-full bg-indicator-error/70 border border-white" }),
8345
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-text-600 font-medium text-sm", children: "Resposta incorreta" })
8346
+ ] })
8347
+ ]
8348
+ }
8349
+ ),
8350
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
8351
+ "button",
8352
+ {
8353
+ "data-testid": "quiz-image-button",
8354
+ type: "button",
8355
+ className: "relative cursor-pointer w-full h-full border-0 bg-transparent p-0",
8356
+ onClick: handleImageClick,
8357
+ onKeyDown: (e) => {
8358
+ if (e.key === "Enter" || e.key === " ") {
8359
+ e.preventDefault();
8360
+ handleKeyboardActivate();
8361
+ }
8362
+ },
8363
+ "aria-label": "\xC1rea da imagem interativa",
8364
+ children: [
8365
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8366
+ "img",
8367
+ {
8368
+ "data-testid": "quiz-image",
8369
+ src: mock_image_question_default,
8370
+ alt: "Question",
8371
+ className: "w-full h-auto rounded-md"
8372
+ }
8373
+ ),
8374
+ variant === "result" && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8375
+ "div",
8376
+ {
8377
+ "data-testid": "quiz-correct-circle",
8378
+ className: "absolute rounded-full bg-indicator-primary/70 border-4 border-[#F8CC2E] pointer-events-none",
8379
+ style: {
8380
+ minWidth: "50px",
8381
+ maxWidth: "160px",
8382
+ width: "15%",
8383
+ aspectRatio: "1 / 1",
8384
+ left: `calc(${correctPositionRelative.x * 100}% - 7.5%)`,
8385
+ top: `calc(${correctPositionRelative.y * 100}% - 15%)`
8386
+ }
8387
+ }
8388
+ ),
8389
+ clickPositionRelative && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8390
+ "div",
8391
+ {
8392
+ "data-testid": "quiz-user-circle",
8393
+ className: `absolute rounded-full border-4 pointer-events-none ${getUserCircleColorClasses()}`,
8394
+ style: {
8395
+ minWidth: "30px",
8396
+ maxWidth: "52px",
8397
+ width: "5%",
8398
+ aspectRatio: "1 / 1",
8399
+ left: `calc(${clickPositionRelative.x * 100}% - 2.5%)`,
8400
+ top: `calc(${clickPositionRelative.y * 100}% - 2.5%)`
8401
+ }
8402
+ }
8403
+ )
8404
+ ]
8405
+ }
8406
+ )
8407
+ ]
8408
+ }
8409
+ ) })
8410
+ ] });
8411
+ };
8266
8412
  var QuizQuestionList = ({
8267
8413
  filterType = "all",
8268
8414
  onQuestionClick
@@ -8344,6 +8490,7 @@ var QuizFooter = (0, import_react25.forwardRef)(
8344
8490
  className,
8345
8491
  onGoToSimulated,
8346
8492
  onDetailResult,
8493
+ handleFinishSimulated,
8347
8494
  variant = "default",
8348
8495
  ...props
8349
8496
  }, ref) => {
@@ -8373,6 +8520,34 @@ var QuizFooter = (0, import_react25.forwardRef)(
8373
8520
  const unansweredQuestions = getUnansweredQuestionsFromUserAnswers();
8374
8521
  const userAnswers = getUserAnswers();
8375
8522
  const allQuestions = getTotalQuestions();
8523
+ const handleFinishQuiz = async () => {
8524
+ if (unansweredQuestions.length > 0) {
8525
+ setAlertDialogOpen(true);
8526
+ return;
8527
+ }
8528
+ try {
8529
+ if (handleFinishSimulated) {
8530
+ await Promise.resolve(handleFinishSimulated());
8531
+ }
8532
+ setModalResultOpen(true);
8533
+ } catch (err) {
8534
+ console.error("handleFinishSimulated failed:", err);
8535
+ setModalResultOpen(true);
8536
+ }
8537
+ };
8538
+ const handleAlertSubmit = async () => {
8539
+ try {
8540
+ if (handleFinishSimulated) {
8541
+ await Promise.resolve(handleFinishSimulated());
8542
+ }
8543
+ setModalResultOpen(true);
8544
+ setAlertDialogOpen(false);
8545
+ } catch (err) {
8546
+ console.error("handleFinishSimulated failed:", err);
8547
+ setModalResultOpen(true);
8548
+ setAlertDialogOpen(false);
8549
+ }
8550
+ };
8376
8551
  return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
8377
8552
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8378
8553
  "footer",
@@ -8438,13 +8613,7 @@ var QuizFooter = (0, import_react25.forwardRef)(
8438
8613
  variant: "solid",
8439
8614
  action: "primary",
8440
8615
  disabled: !currentAnswer && !isCurrentQuestionSkipped,
8441
- onClick: () => {
8442
- if (unansweredQuestions.length > 0) {
8443
- setAlertDialogOpen(true);
8444
- } else {
8445
- setModalResultOpen(true);
8446
- }
8447
- },
8616
+ onClick: handleFinishQuiz,
8448
8617
  children: "Finalizar"
8449
8618
  }
8450
8619
  ) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
@@ -8473,9 +8642,7 @@ var QuizFooter = (0, import_react25.forwardRef)(
8473
8642
  description: unansweredQuestions.length > 0 ? `Voc\xEA deixou as quest\xF5es ${unansweredQuestions.join(", ")} sem resposta. Finalizar agora pode impactar seu desempenho.` : "Tem certeza que deseja finalizar o simulado?",
8474
8643
  cancelButtonLabel: "Voltar e revisar",
8475
8644
  submitButtonLabel: "Finalizar Mesmo Assim",
8476
- onSubmit: () => {
8477
- setModalResultOpen(true);
8478
- }
8645
+ onSubmit: handleAlertSubmit
8479
8646
  }
8480
8647
  ),
8481
8648
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
@@ -8860,6 +9027,7 @@ var QuizListResultByMateria = ({
8860
9027
  QuizFooter,
8861
9028
  QuizHeader,
8862
9029
  QuizHeaderResult,
9030
+ QuizImageQuestion,
8863
9031
  QuizListResult,
8864
9032
  QuizListResultByMateria,
8865
9033
  QuizMultipleChoice,